instructure/canvas-lms · error · BasicLTI::Errors::InvalidSourceId
assignment_invalid
assignment_invalid
Error message
Assignment is invalid
What it means
BasicLti::Sourcedid#validate! raises Errors::InvalidSourceId with :assignment_invalid when the assignment referenced by the sourcedid token cannot be found (Assignment lookup returned nil). This means the assignment was deleted, or its id in the token no longer resolves, so LTI operations tied to it must stop.
Solutions
- Re-launch the tool to get a sourcedid bound to a valid assignment.
- Check Assignment.where(id: assignment_id).exists? before calling APIs with the stored sourcedid.
- Remove the stale sourcedid from your data store; re-create the assignment in Canvas if it was deleted by mistake.
- Verify the sourcedid token was not truncated or corrupted so the correct assignment_id is parsed.
Example fix
// before
sourcedid = BasicLti::Sourcedid.load!(params[:lis_result_sourcedid])
// after
unless Assignment.where(id: parsed_assignment_id).exists?
Rails.logger.warn("assignment gone; re-launch required")
end
sourcedid = BasicLti::Sourcedid.load!(params[:lis_result_sourcedid]) Defensive patterns
Strategy: validation
Validate before calling
# ruby Assignment.where(id: assignment_id).exists? or raise "assignment deleted"
Try / catch
begin BasicLti::Sourcedid.load!(sourcedid) rescue BasicLti::Sourcedid::Errors::InvalidSourceId => e drop_sync_entry if e.error_code == :assignment_invalid end
Prevention
- Check Assignment.exists? before passback for stored sourcedids.
- Clean up tool-side grade columns when the Canvas assignment is deleted via live events.
- Never hard-code assignment ids into sourcedid-like strings.
When it happens
Trigger: Sourcedid.load!(sourcedid) with a token whose assignment_id was deleted; grade passback for an assignment removed from the course between launch and the tool call.
Common situations: Teacher deleted or unpublished-and-deleted the external-tool assignment while students still have tool-side grade column data; stale sourcedids stored by an external gradebook syncing after the assignment is gone.
Understand the failure class
Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.
Related errors
- Access token expired
- Access token invalid - signature likely incorrect
- An assignment with that id does not exist
- Assignment not configured for external tool launches
- Assignment not configured for launches with specified tool
AI-assisted analysis of instructure/canvas-lms@1c9f0bb801 (2026-09-15).
Data as JSON: /api/errors/3bf54d7f68069cb2.
Report an issue: GitHub.
Appendix: source
Thrown at lib/basic_lti/sourcedid.rb:56
end
def jwt_payload
{
iss: "Canvas",
aud: ["Instructure"],
iat: Time.zone.now.to_i,
tool_id: tool.id,
course_id: course.id,
assignment_id: assignment.id,
user_id: user.id,
}
end
private :jwt_payload
def validate!
raise Errors::InvalidSourceId.new("Course is invalid", :course_invalid) unless course
raise Errors::InvalidSourceId.new("User is no longer in course", :user_not_in_course) unless user
raise Errors::InvalidSourceId.new("Assignment is invalid", :assignment_invalid) unless assignment
tag = assignment.external_tool_tag
raise Errors::InvalidSourceId.new("Assignment is no longer associated with this tool", :assignment_tool_mismatch) unless tag &&
(tool.matches_url?(tag.url, match_queries_exactly: false) || tool.matches_tool_domain?(tag.url)) &&
tool.workflow_state != "deleted"
end
def self.load!(sourcedid_string)
raise Errors::InvalidSourceId.new("Invalid sourcedid", :sourcedid_invalid) if sourcedid_string.blank?
token = load_from_legacy_sourcedid!(sourcedid_string) ||
token_from_sourcedid!(sourcedid_string)
tool = Lti::ToolFinder.find_by(id: token[:tool_id])
course = Course.active.find_by(id: token[:course_id])
if course
user = course.student_enrollments.active.find_by(user_id: token[:user_id])&.user
assignment = course.assignments.active.find_by(id: token[:assignment_id])View on GitHub (pinned to 1c9f0bb801)