{"record":{"id":"f46cf0b5180ae340","repo":"instructure/canvas-lms","slug":"assignment-not-configured-for-external-tool-launches","errorCode":null,"errorMessage":"Assignment not configured for external tool launches","messagePattern":"Assignment not configured for external tool launches","errorType":"exception","errorClass":"Lti::IMS::AdvantageErrors::InvalidLaunchError","httpStatus":null,"severity":"error","filePath":"lib/lti/messages/resource_link_request.rb","lineNumber":104,"sourceCode":"      resource_link&.resource_link_uuid || Lti::V1p1::Asset.opaque_identifier_for(@context)\n    end\n\n    def unexpanded_custom_parameters\n      # Add in link-specific custom params (e.g. created by deep linking)\n      super.merge(resource_link&.custom || {})\n    end\n\n    def resource_link\n      assignment_resource_link || @opts[:resource_link]\n    end\n\n    def assignment_resource_link\n      return if @assignment.nil?\n\n      unless defined?(@assignment_resource_link)\n        launch_error = Lti::IMS::AdvantageErrors::InvalidLaunchError\n        unless @assignment.external_tool?\n          raise launch_error.new(nil, api_message: \"Assignment not configured for external tool launches\")\n        end\n        unless Lti::ToolFinder.from_assignment(@assignment) == @tool\n          raise launch_error.new(nil, api_message: \"Assignment not configured for launches with specified tool\")\n        end\n\n        @assignment_resource_link = line_item_for_assignment&.resource_link\n      end\n\n      @assignment_resource_link\n    end\n\n    def line_item_for_assignment\n      @line_item_for_assignment ||= @assignment&.line_items&.find(&:assignment_line_item?)\n    end\n\n    # follows the spec at https://www.imsglobal.org/spec/lti-ags/v2p0/#assignment-and-grade-service-claim\n    # and only adds the 'lineitem' property \"when the LTI message is launching a resource associated\n    # to one and only one line item\"","sourceCodeStart":86,"sourceCodeEnd":122,"githubUrl":"https://github.com/instructure/canvas-lms/blob/1c9f0bb8013ed69c4f2efe11fd483025469b7e6c/lib/lti/messages/resource_link_request.rb#L86-L122","documentation":"assignment_resource_link in lib/lti/messages/resource_link_request.rb:104 raises Lti::IMS::AdvantageErrors::InvalidLaunchError when building an assignment resource link for an assignment that is not an external tool assignment. A resource link request can only be generated for assignments configured with an LTI tool, so non-tool assignments abort the launch.","triggerScenarios":"Generating an LTI resource link request (AGS/Advantage launch) for @assignment that is not external_tool?; tool/assignment mismatch also raises with the 'launches with specified tool' message on the next check.","commonSituations":"LTI 1.3 launches triggered for ordinary canvas assignments; deep-linking or NRPS flows pointed at the wrong assignment id; a tool changed the assignment type after launch configuration.","solutions":["Verify the assignment is created with submission_type 'external_tool' and points at the correct tool before launching","Check that Lti::ToolFinder.from_assignment(assignment) matches the launching @tool if you expect a tool launch","Rescue InvalidLaunchError and return a 4xx with the api_message instead of attempting the launch","Recreate/fix the assignment's external tool configuration if it was changed incorrectly"],"exampleFix":"// before\nResourceLinkRequest.create(tool:, context:, assignment: plain_assignment, ...)\n// after\nraise InvalidLaunchError unless plain_assignment.external_tool?\nResourceLinkRequest.create(tool:, context:, assignment: plain_assignment, ...)","handlingStrategy":"validation","validationCode":"raise InvalidLaunchError unless assignment.external_tool? && Lti::ToolFinder.from_assignment(assignment) == tool","typeGuard":null,"tryCatchPattern":"begin\n  resource_link = builder.assignment_resource_link\nrescue Lti::IMS::AdvantageErrors::InvalidLaunchError => e\n  render json: {error: e.api_message}, status: :bad_request\nend","preventionTips":["Confirm assignment type and tool binding before building launch messages","Rescue InvalidLaunchError in all launch builders","Guard against assignments whose tool config changed after creation"],"tags":["ruby","lti","launch-validation"],"backgroundTag":"invalid-argument-value","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"}