{"record":{"id":"cb1f43c080eb34b1","repo":"CanCanCommunity/cancancan","slug":"you-are-not-authorized-to-access-this-page-cb1f43","errorCode":null,"errorMessage":"You are not authorized to access this page.","messagePattern":"You are not authorized to access this page\\.","errorType":"exception","errorClass":"CanCan::AccessDenied","httpStatus":null,"severity":"error","filePath":"lib/cancan/controller_resource_loader.rb","lineNumber":82,"sourceCode":"      @options[:through] && [@options[:through]].flatten.detect { |i| fetch_parent(i) }\n    end\n\n    def resource_base_through_parent_resource\n      if @options[:singleton]\n        resource_class\n      else\n        parent_resource.send(@options[:through_association] || name.to_s.pluralize)\n      end\n    end\n\n    def resource_base_through\n      if parent_resource\n        resource_base_through_parent_resource\n      elsif @options[:shallow]\n        resource_class\n      else\n        # maybe this should be a record not found error instead?\n        raise AccessDenied.new(nil, authorization_action, resource_class)\n      end\n    end\n\n    # The object that methods (such as \"find\", \"new\" or \"build\") are called on.\n    # If the :through option is passed it will go through an association on that instance.\n    # If the :shallow option is passed it will use the resource_class if there's no parent\n    # If the :singleton option is passed it won't use the association because it needs to be handled later.\n    def resource_base\n      @options[:through] ? resource_base_through : resource_class\n    end\n\n    def parent_authorization_action\n      @options[:parent_action] || :show\n    end\n\n    def authorization_action\n      parent? ? parent_authorization_action : @params[:action].to_sym\n    end","sourceCodeStart":64,"sourceCodeEnd":100,"githubUrl":"https://github.com/CanCanCommunity/cancancan/blob/8c1bf153a3da7b2261d6fa4a5f84eb28e2feb828/lib/cancan/controller_resource_loader.rb#L64-L100","documentation":"Raised by ControllerResourceLoader#resource_base_through (lib/cancan/controller_resource_loader.rb:82) while building the resource base for load_and_authorize_resource with the through: option. When no parent resource could be loaded and :shallow is not set, CanCanCan has no parent association to scope through and cannot even construct the query, so it raises CanCan::AccessDenied (with a nil/default message). The source comment notes this arguably should be a record-not-found error.","triggerScenarios":"load_and_authorize_resource through: :project in a controller, but the request hits a route where params[:project_id] is absent so parent_resource is nil; the parent lookup returns nil (deleted record); through_association misconfigured so the parent never loads; using both nested and non-nested routes without shallow: true.","commonSituations":"Shallow-style routes mixed with nested through: resources and shallow: true forgotten; parent param named differently than the controller guesses; the parent record was destroyed but child routes still reachable; upgrading an app where route nesting changed.","solutions":["Add shallow: true when the resource is reachable both nested and non-nested: load_and_authorize_resource through: :project, shallow: true.","Ensure the parent loads: correct route nesting, correct param name, and the through:/through_association options match the association.","If the parent is mandatory, 404 early in the controller (raise ActiveRecord::RecordNotFound when the parent param is missing) before authorization runs.","Keep the global rescue_from CanCan::AccessDenied as a safety net for UX."],"exampleFix":"# before\nclass CommentsController < ApplicationController\n  load_and_authorize_resource through: :project\n  # GET /comments (non-nested) -> parent_resource nil -> AccessDenied\nend\n\n# after\nclass CommentsController < ApplicationController\n  load_and_authorize_resource through: :project, shallow: true\nend","handlingStrategy":"validation","validationCode":"# run before load_and_authorize_resource builds the base (before_action)\nraise ActiveRecord::RecordNotFound, 'parent project required' if params[:project_id].blank?","typeGuard":null,"tryCatchPattern":"rescue_from CanCan::AccessDenied do |exception|\n  redirect_to root_path, alert: 'Resource unavailable' # covers the nil-parent through: case too\nend","preventionTips":["Add shallow: true whenever routes expose the child both nested and non-nested.","Keep parent param names conventional (model_id) so ControllerAdditions finds them.","Write controller specs hitting the non-nested route for every through: resource.","If the parent is mandatory, 404 early in a before_action instead of letting authorization fail."],"tags":["authorization","nested-resources","through-option","cancancan","rails"],"backgroundTag":"missing-parent-resource","analyzedSha":"8c1bf153a3da7b2261d6fa4a5f84eb28e2feb828","analyzedAt":"2026-08-21T20:05:55.000Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}