{"record":{"id":"210b2e3c616c4d09","repo":"CanCanCommunity/cancancan","slug":"this-action-failed-the-check-authorization-because","errorCode":null,"errorMessage":"This action failed the check_authorization because it does not authorize_resource. Add skip_authorization_check to bypass this check.","messagePattern":"This action failed the check_authorization because it does not authorize_resource\\. Add skip_authorization_check to bypass this check\\.","errorType":"exception","errorClass":"CanCan::AuthorizationNotPerformed","httpStatus":null,"severity":"error","filePath":"lib/cancan/controller_additions.rb","lineNumber":271,"sourceCode":"      # [:+if+]\n      #   Supply the name of a controller method to be called.\n      #   The authorization check only takes place if this returns true.\n      #\n      #     check_authorization :if => :admin_controller?\n      #\n      # [:+unless+]\n      #   Supply the name of a controller method to be called.\n      #   The authorization check only takes place if this returns false.\n      #\n      #     check_authorization :unless => :devise_controller?\n      #\n      def check_authorization(options = {})\n        block = proc do |controller|\n          next if controller.instance_variable_defined?(:@_authorized)\n          next if options[:if] && !controller.send(options[:if])\n          next if options[:unless] && controller.send(options[:unless])\n\n          raise AuthorizationNotPerformed,\n                'This action failed the check_authorization because it does not authorize_resource. ' \\\n                'Add skip_authorization_check to bypass this check.'\n        end\n\n        send(:after_action, options.slice(:only, :except), &block)\n      end\n\n      # Call this in the class of a controller to skip the check_authorization behavior on the actions.\n      #\n      #   class HomeController < ApplicationController\n      #     skip_authorization_check :only => :index\n      #   end\n      #\n      # Any arguments are passed to the +before_action+ it triggers.\n      def skip_authorization_check(*args)\n        block = proc { |controller| controller.instance_variable_set(:@_authorized, true) }\n        send(:before_action, *args, &block)\n      end","sourceCodeStart":253,"sourceCodeEnd":289,"githubUrl":"https://github.com/CanCanCommunity/cancancan/blob/8c1bf153a3da7b2261d6fa4a5f84eb28e2feb828/lib/cancan/controller_additions.rb#L253-L289","documentation":"check_authorization (lib/cancan/controller_additions.rb:271) installs an after_action callback that raises CanCan::AuthorizationNotPerformed unless the action actually performed an authorization decision (tracked via the @_authorized instance variable set by authorize!/authorize/load_and_authorize_resource). It is a safety net so no controller action ships without an explicit authorization choice; :if/:unless options skip the check for named controller methods.","triggerScenarios":"ApplicationController declares check_authorization; any action in any controller that never calls authorize, authorize!, authorize_resource, or load_and_authorize_resource; controllers that only use can? in views (can? does not set @_authorized); Devise or other engine controllers not excluded via check_authorization unless: :devise_controller?.","commonSituations":"Adding public pages (home, about, health endpoints) and forgetting to skip; introducing a new namespaced controller while the ability rules live only in view guards; engines mounting controllers that bypass the app's authorize conventions.","solutions":["Add authorize_resource or load_and_authorize_resource to the controller (preferred — the check exists to force this).","For deliberately public actions, add skip_authorization_check :only => :index (or at the controller class level for fully public controllers).","Exclude whole groups: check_authorization :unless => :devise_controller? or an :if predicate.","For symbol subjects (pages with no model), call authorize! :read, :dashboard inside the action."],"exampleFix":"# before\nclass ApplicationController < ActionController::Base\n  check_authorization\nend\n\nclass HomeController < ApplicationController\n  def index; end  # raises AuthorizationNotPerformed\nend\n\n# after\nclass HomeController < ApplicationController\n  skip_authorization_check only: :index\n  def index; end\nend","handlingStrategy":"validation","validationCode":"# controller-level: make the decision explicit instead of forgetting it\nclass HomeController < ApplicationController\n  skip_authorization_check only: :index # deliberate, visible choice\nend","typeGuard":null,"tryCatchPattern":"rescue_from CanCan::AuthorizationNotPerformed do |exception|\n  Rails.logger.error(\"NO AUTHORIZATION: #{params[:controller]}##{params[:action]}\")\n  render file: 'public/500', status: :internal_server_error # fail loudly in dev\nend","preventionTips":["Keep check_authorization in ApplicationController with unless: :devise_controller? from day one.","Prefer authorize_resource over skip_authorization_check when in doubt.","Add a CI spec enumerating routes and asserting each protected action sets @_authorized.","Treat a new AuthorizationNotPerformed as a build failure, never silence it in production."],"tags":["authorization","controller-check","rails","cancancan"],"backgroundTag":"missing-authorization-check","analyzedSha":"8c1bf153a3da7b2261d6fa4a5f84eb28e2feb828","analyzedAt":"2026-08-21T20:05:55.000Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}