Rails' ActiveRecord::Encryption on User attributes (email and/or id) prevents the error message from being returned (when values empty)
Environment
- Ruby: ruby 3.0.1p64 (2021-04-05 revision 0fb782ee38) [x86_64-linux]
- Rails: Rails 7.0.4
- Devise: devise 4.8.1
Current behavior
When the User model has attributes (email and/or id) encrypted (using Rails' Active Record Encryption) and then, an empty "Sign up" form is submitted, the server returns a 500 Internal Server Error, due to ActiveRecord::Encryption::Errors::Decryption (ActiveRecord::Encryption::Errors::Decryption) being triggered by the line resource.save in Devise's RegistrationsController.
Expected behavior
Instead, a validation error should be returned (i.e. "Email is required").
Trace
activerecord (7.0.4) lib/active_record/encryption/encryptor.rb:58:in `rescue in decrypt'
activerecord (7.0.4) lib/active_record/encryption/encryptor.rb:52:in `decrypt'
activerecord (7.0.4) lib/active_record/encryption/encrypted_attribute_type.rb:73:in `block in decrypt'
activerecord (7.0.4) lib/active_record/encryption/scheme.rb:67:in `with_context'
activerecord (7.0.4) lib/active_record/encryption/encrypted_attribute_type.rb:15:in `with_context'
activerecord (7.0.4) lib/active_record/encryption/encrypted_attribute_type.rb:72:in `decrypt'
activerecord (7.0.4) lib/active_record/encryption/encrypted_attribute_type.rb:31:in `deserialize'
activemodel (7.0.4) lib/active_model/attribute.rb:168:in `type_cast'
activemodel (7.0.4) lib/active_model/attribute.rb:43:in `value'
activemodel (7.0.4) lib/active_model/attribute_set.rb:46:in `fetch_value'
activerecord (7.0.4) lib/active_record/transactions.rb:403:in `block in restore_transaction_record_state'
activemodel (7.0.4) lib/active_model/attribute_set.rb:93:in `transform_values'
activemodel (7.0.4) lib/active_model/attribute_set.rb:93:in `map'
activerecord (7.0.4) lib/active_record/transactions.rb:402:in `restore_transaction_record_state'
activerecord (7.0.4) lib/active_record/transactions.rb:334:in `rolledback!'
activerecord (7.0.4) lib/active_record/connection_adapters/abstract/transaction.rb:134:in `rollback_records'
activerecord (7.0.4) lib/active_record/connection_adapters/abstract/transaction.rb:312:in `block in rollback_transaction'
activesupport (7.0.4) lib/active_support/concurrency/load_interlock_aware_monitor.rb:25:in `handle_interrupt'
activesupport (7.0.4) lib/active_support/concurrency/load_interlock_aware_monitor.rb:25:in `block in synchronize'
activesupport (7.0.4) lib/active_support/concurrency/load_interlock_aware_monitor.rb:21:in `handle_interrupt'
activesupport (7.0.4) lib/active_support/concurrency/load_interlock_aware_monitor.rb:21:in `synchronize'
activerecord (7.0.4) lib/active_record/connection_adapters/abstract/transaction.rb:309:in `rollback_transaction'
activerecord (7.0.4) lib/active_record/connection_adapters/abstract/transaction.rb:325:in `rescue in block in within_new_transaction'
activerecord (7.0.4) lib/active_record/connection_adapters/abstract/transaction.rb:322:in `block in within_new_transaction'
activesupport (7.0.4) lib/active_support/concurrency/load_interlock_aware_monitor.rb:25:in `handle_interrupt'
activesupport (7.0.4) lib/active_support/concurrency/load_interlock_aware_monitor.rb:25:in `block in synchronize'
activesupport (7.0.4) lib/active_support/concurrency/load_interlock_aware_monitor.rb:21:in `handle_interrupt'
activesupport (7.0.4) lib/active_support/concurrency/load_interlock_aware_monitor.rb:21:in `synchronize'
activerecord (7.0.4) lib/active_record/connection_adapters/abstract/transaction.rb:317:in `within_new_transaction'
activerecord (7.0.4) lib/active_record/connection_adapters/abstract/database_statements.rb:316:in `transaction'
activerecord (7.0.4) lib/active_record/transactions.rb:350:in `with_transaction_returning_status'
activerecord (7.0.4) lib/active_record/transactions.rb:298:in `save'
activerecord (7.0.4) lib/active_record/suppressor.rb:50:in `save'
app/controllers/users/registrations_controller.rb:96:in `create'
actionpack (7.0.4) lib/action_controller/metal/basic_implicit_render.rb:6:in `send_action'
actionpack (7.0.4) lib/abstract_controller/base.rb:215:in `process_action'
actionpack (7.0.4) lib/action_controller/metal/rendering.rb:53:in `process_action'
actionpack (7.0.4) lib/abstract_controller/callbacks.rb:234:in `block in process_action'
activesupport (7.0.4) lib/active_support/callbacks.rb:118:in `block in run_callbacks'
actiontext (7.0.4) lib/action_text/rendering.rb:20:in `with_renderer'
actiontext (7.0.4) lib/action_text/engine.rb:69:in `block (4 levels) in <class:Engine>'
activesupport (7.0.4) lib/active_support/callbacks.rb:127:in `instance_exec'
activesupport (7.0.4) lib/active_support/callbacks.rb:127:in `block in run_callbacks'
activesupport (7.0.4) lib/active_support/callbacks.rb:138:in `run_callbacks'
actionpack (7.0.4) lib/abstract_controller/callbacks.rb:233:in `process_action'
actionpack (7.0.4) lib/action_controller/metal/rescue.rb:22:in `process_action'
actionpack (7.0.4) lib/action_controller/metal/instrumentation.rb:67:in `block in process_action'
activesupport (7.0.4) lib/active_support/notifications.rb:206:in `block in instrument'
activesupport (7.0.4) lib/active_support/notifications/instrumenter.rb:24:in `instrument'
activesupport (7.0.4) lib/active_support/notifications.rb:206:in `instrument'
actionpack (7.0.4) lib/action_controller/metal/instrumentation.rb:66:in `process_action'
actionpack (7.0.4) lib/action_controller/metal/params_wrapper.rb:259:in `process_action'
activerecord (7.0.4) lib/active_record/railties/controller_runtime.rb:27:in `process_action'
actionpack (7.0.4) lib/abstract_controller/base.rb:151:in `process'
actionview (7.0.4) lib/action_view/rendering.rb:39:in `process'
actionpack (7.0.4) lib/action_controller/metal.rb:188:in `dispatch'
actionpack (7.0.4) lib/action_controller/metal.rb:251:in `dispatch'
actionpack (7.0.4) lib/action_dispatch/routing/route_set.rb:49:in `dispatch'
actionpack (7.0.4) lib/action_dispatch/routing/route_set.rb:32:in `serve'
actionpack (7.0.4) lib/action_dispatch/routing/mapper.rb:18:in `block in <class:Constraints>'
actionpack (7.0.4) lib/action_dispatch/routing/mapper.rb:48:in `serve'
actionpack (7.0.4) lib/action_dispatch/journey/router.rb:50:in `block in serve'
actionpack (7.0.4) lib/action_dispatch/journey/router.rb:32:in `each'
actionpack (7.0.4) lib/action_dispatch/journey/router.rb:32:in `serve'
actionpack (7.0.4) lib/action_dispatch/routing/route_set.rb:852:in `call'
http_accept_language (2.1.1) lib/http_accept_language/middleware.rb:14:in `call'
warden (1.2.9) lib/warden/manager.rb:36:in `block in call'
warden (1.2.9) lib/warden/manager.rb:34:in `catch'
warden (1.2.9) lib/warden/manager.rb:34:in `call'
rack (2.2.5) lib/rack/tempfile_reaper.rb:15:in `call'
rack (2.2.5) lib/rack/etag.rb:27:in `call'
rack (2.2.5) lib/rack/conditional_get.rb:40:in `call'
rack (2.2.5) lib/rack/head.rb:12:in `call'
actionpack (7.0.4) lib/action_dispatch/http/permissions_policy.rb:38:in `call'
actionpack (7.0.4) lib/action_dispatch/http/content_security_policy.rb:36:in `call'
rack (2.2.5) lib/rack/session/abstract/id.rb:266:in `context'
rack (2.2.5) lib/rack/session/abstract/id.rb:260:in `call'
actionpack (7.0.4) lib/action_dispatch/middleware/cookies.rb:696:in `call'
activerecord (7.0.4) lib/active_record/migration.rb:603:in `call'
actionpack (7.0.4) lib/action_dispatch/middleware/callbacks.rb:27:in `block in call'
activesupport (7.0.4) lib/active_support/callbacks.rb:99:in `run_callbacks'
actionpack (7.0.4) lib/action_dispatch/middleware/callbacks.rb:26:in `call'
actionpack (7.0.4) lib/action_dispatch/middleware/executor.rb:14:in `call'
actionpack (7.0.4) lib/action_dispatch/middleware/actionable_exceptions.rb:17:in `call'
actionpack (7.0.4) lib/action_dispatch/middleware/debug_exceptions.rb:28:in `call'
web-console (4.2.0) lib/web_console/middleware.rb:132:in `call_app'
web-console (4.2.0) lib/web_console/middleware.rb:28:in `block in call'
web-console (4.2.0) lib/web_console/middleware.rb:17:in `catch'
web-console (4.2.0) lib/web_console/middleware.rb:17:in `call'
actionpack (7.0.4) lib/action_dispatch/middleware/show_exceptions.rb:26:in `call'
railties (7.0.4) lib/rails/rack/logger.rb:40:in `call_app'
railties (7.0.4) lib/rails/rack/logger.rb:25:in `block in call'
activesupport (7.0.4) lib/active_support/tagged_logging.rb:99:in `block in tagged'
activesupport (7.0.4) lib/active_support/tagged_logging.rb:37:in `tagged'
activesupport (7.0.4) lib/active_support/tagged_logging.rb:99:in `tagged'
railties (7.0.4) lib/rails/rack/logger.rb:25:in `call'
sprockets-rails (3.4.2) lib/sprockets/rails/quiet_assets.rb:13:in `call'
actionpack (7.0.4) lib/action_dispatch/middleware/remote_ip.rb:93:in `call'
request_store (1.5.1) lib/request_store/middleware.rb:19:in `call'
actionpack (7.0.4) lib/action_dispatch/middleware/request_id.rb:26:in `call'
rack (2.2.5) lib/rack/method_override.rb:24:in `call'
rack (2.2.5) lib/rack/runtime.rb:22:in `call'
activesupport (7.0.4) lib/active_support/cache/strategy/local_cache_middleware.rb:29:in `call'
actionpack (7.0.4) lib/action_dispatch/middleware/server_timing.rb:61:in `block in call'
actionpack (7.0.4) lib/action_dispatch/middleware/server_timing.rb:26:in `collect_events'
actionpack (7.0.4) lib/action_dispatch/middleware/server_timing.rb:60:in `call'
actionpack (7.0.4) lib/action_dispatch/middleware/executor.rb:14:in `call'
actionpack (7.0.4) lib/action_dispatch/middleware/static.rb:23:in `call'
rack (2.2.5) lib/rack/sendfile.rb:110:in `call'
actionpack (7.0.4) lib/action_dispatch/middleware/host_authorization.rb:137:in `call'
railties (7.0.4) lib/rails/engine.rb:530:in `call'
puma (5.6.5) lib/puma/configuration.rb:252:in `call'
puma (5.6.5) lib/puma/request.rb:77:in `block in handle_request'
puma (5.6.5) lib/puma/thread_pool.rb:340:in `with_force_shutdown'
puma (5.6.5) lib/puma/request.rb:76:in `handle_request'
puma (5.6.5) lib/puma/server.rb:443:in `process_client'
puma (5.6.5) lib/puma/thread_pool.rb:147:in `block in spawn_thread'
I believe this comment can help https://github.com/heartcombo/devise/issues/5436#issuecomment-1014152052
If you want to raise an error from the request, you can edit the permitted params to make email required (yet it's not recommended in rails community to do so)