{"record":{"id":"db9a980a04707990","repo":"heartcombo/devise","slug":"devise-doesn-t-know-how-to-sanitize-parameters-fo","errorCode":null,"errorMessage":"\"Devise doesn't know how to sanitize parameters for '#{action}'\".\nIf you want to define a new set of parameters to be sanitized use the\n`permit` method first:\n\n  devise_parameter_sanitizer.permit(:#{action}, keys: [:param1, :param2, :param3])","messagePattern":"\"Devise doesn't know how to sanitize parameters for '#(.+?)'\"\\.\nIf you want to define a new set of parameters to be sanitized use the\n`permit` method first:\n\n  devise_parameter_sanitizer\\.permit\\(:#(.+?), keys: \\[:param1, :param2, :param3\\]\\)","errorType":"exception","errorClass":"NotImplementedError","httpStatus":null,"severity":"error","filePath":"lib/devise/parameter_sanitizer.rb","lineNumber":163,"sourceCode":"      @params[@resource_name].respond_to?(:permit)\n    end\n\n    def empty_params\n      ActionController::Parameters.new({})\n    end\n\n    def permit_keys(parameters, keys)\n      parameters.permit(*keys)\n    end\n\n    def extract_auth_keys(klass)\n      auth_keys = klass.authentication_keys\n\n      auth_keys.respond_to?(:keys) ? auth_keys.keys : auth_keys\n    end\n\n    def unknown_action!(action)\n      raise NotImplementedError, <<-MESSAGE.strip_heredoc\n        \"Devise doesn't know how to sanitize parameters for '#{action}'\".\n        If you want to define a new set of parameters to be sanitized use the\n        `permit` method first:\n\n          devise_parameter_sanitizer.permit(:#{action}, keys: [:param1, :param2, :param3])\n      MESSAGE\n    end\n  end\nend\n","sourceCodeStart":145,"sourceCodeEnd":173,"githubUrl":"https://github.com/heartcombo/devise/blob/372b295fe6f63b4af3269f5dcd51a18c0bc2016c/lib/devise/parameter_sanitizer.rb#L145-L173","documentation":"Devise::ParameterSanitizer whitelists request parameters per action; defaults are pre-registered only for :sign_in, :sign_up and :account_update (DEFAULT_PERMITTED_ATTRIBUTES). sanitize(action) looks up @permitted[action] and, when nothing was registered for that action (no array and no block), calls unknown_action!, which raises NotImplementedError with instructions to call permit first. It fires whenever you sanitize an action whose permission list was never declared.","triggerScenarios":"A custom Devise controller action calling devise_parameter_sanitizer.sanitize(:accept_invitation) (or any symbol outside sign_in/sign_up/account_update) without a matching devise_parameter_sanitizer.permit(:accept_invitation, keys: [...]) beforehand; a typo making the permit and sanitize symbols differ (permit(:signip) vs sanitize(:sign_in)); code migrated from the old Devise 2.x/3.x sanitizer API that had different default actions.","commonSituations":"Building custom registration or invitation flows on Devise controllers; overriding Devise::RegistrationsController#create and sanitizing a custom action name; large apps that whitelist extra profile fields per action and miss one; refactoring renames an action symbol in one place but not the other.","solutions":["Register the permission list before sanitizing, typically in a before_action: devise_parameter_sanitizer.permit(:accept_invitation, keys: [:invitation_token, :name, :password, :password_confirmation]).","For nested/full control, use the block form: devise_parameter_sanitizer.permit(:accept_invitation) { |u| u.permit(:invitation_token, profile: [:name]) }.","If the action is really one of the standard ones, fix the symbol: sanitize(:sign_up) not sanitize(:signup) — and make sure the permit and sanitize calls use the identical symbol.","Ensure your before_action configure_permitted_parameters runs before the action that sanitizes (declared in ApplicationController with if: :devise_controller?)."],"exampleFix":"# before (custom Devise controller)\nclass Users::InvitationsController < Devise::RegistrationsController\n  def update\n    self.resource = resource_class.accept_invitation(\n      devise_parameter_sanitizer.sanitize(:accept_invitation) # NotImplementedError\n    )\n  end\nend\n\n# after\nclass Users::InvitationsController < Devise::RegistrationsController\n  before_action :configure_invitation_params, only: :update\n\n  def update\n    self.resource = resource_class.accept_invitation(\n      devise_parameter_sanitizer.sanitize(:accept_invitation)\n    )\n  end\n\n  protected\n\n  def configure_invitation_params\n    devise_parameter_sanitizer.permit(\n      :accept_invitation,\n      keys: [:invitation_token, :password, :password_confirmation]\n    )\n  end\nend","handlingStrategy":"validation","validationCode":"# Register every custom action's permissions before any sanitize call:\nclass Users::InvitationsController < Devise::RegistrationsController\n  CUSTOM_SANITIZED_ACTIONS = %i(accept_invitation).freeze\n\n  before_action only: :update do\n    devise_parameter_sanitizer.permit(\n      :accept_invitation,\n      keys: [:invitation_token, :password, :password_confirmation]\n    )\n  end\nend\n\n# If you must check before calling sanitize (introspects the private registry):\ndef sanitizer_registered?(action)\n  devise_parameter_sanitizer\n    .instance_variable_get(:@permitted)\n    .key?(action.to_sym)\nend","typeGuard":"def sanitizable_action?(sanitizer, action)\n  sanitizer.instance_variable_get(:@permitted).key?(action.to_sym)\nend\n# usage: params = sanitizer.sanitize(action) if sanitizable_action?(sanitizer, :accept_invitation)","tryCatchPattern":"# Around a custom sanitize call in code you don't fully control:\nbegin\n  attrs = devise_parameter_sanitizer.sanitize(:accept_invitation)\nrescue NotImplementedError\n  devise_parameter_sanitizer.permit(:accept_invitation, keys: [:invitation_token, :password, :password_confirmation])\n  attrs = devise_parameter_sanitizer.sanitize(:accept_invitation)\nend","preventionTips":["Declare permit for every custom action in a before_action (guarded by if: :devise_controller?) rather than inline in the action.","Define action symbols once (constants or a small registry) and reuse them in both permit and sanitize calls to avoid typo drift.","Remember only :sign_in, :sign_up, :account_update come pre-registered — any other symbol must be permitted first.","Add a request spec per custom sanitized action so an unregistered action fails in CI, not on the first real form submission."],"tags":["devise","rails","strong-parameters","parameter-sanitization","custom-controller"],"backgroundTag":"parameter-sanitizer-unknown-action","analyzedSha":"372b295fe6f63b4af3269f5dcd51a18c0bc2016c","analyzedAt":"2026-08-21T11:55:31.116Z","schemaVersion":2},"datasetVersion":"2026-08-21T13:17:26.733Z"}