{"record":{"id":"50dc873413422cf1","repo":"instructure/canvas-lms","slug":"tool-does-not-have-access-to-requested-context","errorCode":null,"errorMessage":"Tool does not have access to requested context","messagePattern":"Tool does not have access to requested context","errorType":"exception","errorClass":"Lti::SubscriptionsValidator::ToolNotInContext","httpStatus":400,"severity":"error","filePath":"app/controllers/lti/subscriptions_validator.rb","lineNumber":61,"sourceCode":"      @tool_proxy = tool_proxy\n    end\n\n    def check_required_capabilities!\n      capabilities_hash = ToolConsumerProfile.webhook_subscription_capabilities\n      return if tool_proxy.enabled_capabilities.include?(ToolConsumerProfile.webhook_grant_all_capability)\n\n      subscription[:EventTypes].each do |event_type|\n        raise MissingCapability, \"EventType #{event_type} is invalid\" unless capabilities_hash.key?(event_type.to_sym)\n        unless tool_proxy.enabled_capabilities.intersect?(capabilities_hash[event_type.to_sym])\n          raise MissingCapability, \"Missing required capability\"\n        end\n      end\n    end\n\n    def check_tool_context!\n      requested_context = subscription_context\n      requested_context = requested_context.course if requested_context.respond_to?(:course)\n      raise ToolNotInContext, \"Tool does not have access to requested context\" unless tool_proxy.active_in_context?(requested_context)\n    end\n\n    def validate_subscription_request!\n      check_required_capabilities!\n      check_tool_context!\n    end\n\n    def self.validate_subscription_context!(subscription)\n      raise ContextNotFound unless retrieve_context(subscription).present?\n\n      true\n    end\n\n    def self.retrieve_context(subscription)\n      model = CONTEXT_WHITELIST[subscription[:ContextType]]\n      raise InvalidContextType unless model\n\n      case subscription[:ContextType]","sourceCodeStart":43,"sourceCodeEnd":79,"githubUrl":"https://github.com/instructure/canvas-lms/blob/1c9f0bb8013ed69c4f2efe11fd483025469b7e6c/app/controllers/lti/subscriptions_validator.rb#L43-L79","documentation":"Raised by Lti::SubscriptionsValidator#check_tool_context! when the context (course/account) the subscription targets is not one where the tool proxy is active (active_in_context? is false). Canvas refuses to let a tool subscribe to live events from a context it is not installed in.","triggerScenarios":"POSTing a subscription whose context_link/context (resolved via subscription_context, unwrapping course if it is an enrollment) is a course or account where the tool proxy is not installed or has been deactivated/deleted.","commonSituations":"Tool installed only at sub-account level but subscribing to root-account events; tool removed from a course after a subscription was attempted; admin moved course to another account where the tool is not active; using a course context_id belonging to a different account.","solutions":["Install or re-activate the tool proxy in the requested course/account context","Change the subscription's context to one where the tool is active","Verify context_link/context ids resolve to the intended course and not a migrated one","Check tool proxy deployment state (workflow_state active) in the target context"],"exampleFix":"// before\n{ subscription: { ContextType: 'course', ContextId: '123' } } // tool not in course 123\n// after\n{ subscription: { ContextType: 'course', ContextId: '456' } } // tool active in course 456","handlingStrategy":"validation","validationCode":"ctx = resolve_context(context_type, context_id)\nraise 'tool not active in context' unless tool_proxy.active_in_context?(ctx)","typeGuard":null,"tryCatchPattern":"begin\n  validator.validate_subscription_request!\nrescue Lti::SubscriptionsValidator::ToolNotInContext\n  deploy_tool_to_context(context_id) || subscribe_in_active_context\nend","preventionTips":["Confirm tool installation in every context subscribed to","Recheck active status after course/account migrations","Use root account subscription only for root-installed tools"],"tags":["lti","live-events","permissions"],"backgroundTag":"permission-denied","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"}