{"record":{"id":"33298ea80c8f590e","repo":"instructure/canvas-lms","slug":"tool-does-not-have-access-to-rlid-or-rlid-does-not-exist","errorCode":null,"errorMessage":"Tool does not have access to rlid or rlid does not exist","messagePattern":"Tool does not have access to rlid or rlid does not exist","errorType":"exception","errorClass":"Lti::IMS::AdvantageErrors::InvalidResourceLinkIdFilter","httpStatus":404,"severity":"error","filePath":"app/controllers/lti/ims/providers/memberships_provider.rb","lineNumber":117,"sourceCode":"      return nil unless rlid?\n      return @resource_link if defined?(@resource_link)\n\n      rl = Lti::ResourceLink.find_by(resource_link_uuid: rlid)\n      if rl.present?\n        # context here is a decorated context, we want the original\n        current_tool = rl.current_external_tool(Lti::IMS::Providers::MembershipsProvider.unwrap(context))\n        # Allow access if IDs match exactly, or if both are from the same LTI 1.3\n        # registration (same developer key) within the same root account. The latter\n        # handles cases where the same registration is installed at multiple context\n        # levels (e.g., course and account), and a resource link created by one\n        # installation is accessed by another. The root_account_id guard prevents\n        # a global/inherited developer key from granting cross-root-account access.\n        unless current_tool &&\n               (current_tool.id == tool.id ||\n                (tool.use_1_3? && tool.developer_key_id.present? &&\n                 current_tool.developer_key_id == tool.developer_key_id &&\n                 current_tool.root_account_id == tool.root_account_id))\n          raise Lti::IMS::AdvantageErrors::InvalidResourceLinkIdFilter.new(\n            \"Tool does not have access to rlid #{rlid}\",\n            api_message: \"Tool does not have access to rlid or rlid does not exist\"\n          )\n        end\n      end\n\n      @resource_link = rl\n    end\n\n    def content_tag\n      return nil unless resource_link\n\n      ContentTag.find_by(associated_asset: resource_link)\n    end\n\n    def role\n      controller.params[:role]\n    end","sourceCodeStart":99,"sourceCodeEnd":135,"githubUrl":"https://github.com/instructure/canvas-lms/blob/1c9f0bb8013ed69c4f2efe11fd483025469b7e6c/app/controllers/lti/ims/providers/memberships_provider.rb#L99-L135","documentation":"Guard in MembershipsProvider#resource_link: for an NRPS request with an rlid, either the tool lacks access to that Lti::ResourceLink or the rlid doesn't resolve — the resource link's current external tool doesn't match the requesting tool (by id or by same registration/dev key in the root account). Raised as InvalidResourceLinkIdFilter.","triggerScenarios":"Thrown at app/controllers/lti/ims/providers/memberships_provider.rb:117 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Ensure the LTI launch/NRPS call uses the same tool (or registration dev key) that owns the resource link","Verify the rlid value matches an existing Lti::ResourceLink uuid"],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"1c9f0bb8013ed69c4f2efe11fd483025469b7e6c","analyzedAt":"2026-09-15T20:33:18.891Z","contentChangedAt":"2026-09-15T20:33:18.891Z","schemaVersion":2},"datasetVersion":"2026-09-23T02:17:17.105Z"}