instructure/canvas-lms · error · BasicLTI::Errors::InvalidSourceId
signature_invalid
signature_invalid
Error message
Invalid signature
What it means
Sourcedid.load_from_legacy_sourcedid! raises Errors::InvalidSourceId with :signature_invalid when the legacy sourcedid's HMAC-SHA1 signature does not verify against the tool shard's encryption_key. The token was tampered with, constructed with a different key, or the key changed.
Solutions
- Re-launch the tool in the correct environment to get a validly signed sourcedid.
- Confirm the sourcedid is being verified on the same shard that signed it (check tool.shard.settings[:encryption_key]).
- Do not modify sourcedid segments in transit; treat them as opaque strings.
- If keys were rotated, existing legacy sourcedids are invalid — migrate to JWT-based sourcedids.
Example fix
// before sd = sourcedid_from_other_env # signed with different key BasicLti::Sourcedid.load!(sd) # InvalidSourceId :signature_invalid // after sd = fresh_sourcedid_from_launch # signed by this environment's key BasicLti::Sourcedid.load!(sd)
Defensive patterns
Strategy: try-catch
Try / catch
begin BasicLti::Sourcedid.load!(sourcedid) rescue BasicLti::Sourcedid::Errors::InvalidSourceId => e request_fresh_launch if e.error_code == :signature_invalid end
Prevention
- Never move sourcedids between Canvas environments with different encryption keys.
- Treat sourcedid segments as immutable; sign once at launch.
- Coordinate shard encryption_key rotations with a sourcedid re-issue plan.
When it happens
Trigger: Verifying md[5] via Canvas::Security.verify_hmac_sha1(md[5], new_encoding, key: tool.shard.settings[:encryption_key]) and it returns false — e.g. the sourcedid was signed on a shard/account with a different encryption key, or the id segments (md[1..4]) were altered.
Common situations: Copying sourcedids between Canvas environments (prod/test) with different encryption keys; shard settings[:encryption_key] regenerated; hand-crafted sourcedids in scripts; truncation that changes the signed payload.
Understand the failure class
Background: Checksum mismatch errors: "checksum verification failed", "digest mismatch", "expected vs actual checksum" — what they mean and how to fix them — this error's family across 41 libraries.
Related errors
- Invalid analytics service token
- Invalid logout service token
- signature doesn't match.
- Access token expired
- Access token invalid - signature likely incorrect
AI-assisted analysis of instructure/canvas-lms@1c9f0bb801 (2026-09-15).
Data as JSON: /api/errors/ced28bd7da8d2a9c.
Report an issue: GitHub.
Appendix: source
Thrown at lib/basic_lti/sourcedid.rb:90
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])
end
sourcedid = new(tool, course, assignment, user)
sourcedid.validate!
sourcedid
end
def self.load_from_legacy_sourcedid!(sourcedid)
token = nil
md = sourcedid.match(SOURCE_ID_REGEX)
if md
tool = Lti::ToolFinder.find_by(id: md[1])
raise Errors::InvalidSourceId.new("Tool is invalid", :tool_invalid) unless tool
new_encoding = [md[1], md[2], md[3], md[4]].join("-")
raise Errors::InvalidSourceId.new("Invalid signature", :signature_invalid) unless Canvas::Security
.verify_hmac_sha1(md[5], new_encoding, key: tool.shard.settings[:encryption_key])
token = { tool_id: md[1].to_i, course_id: md[2], assignment_id: md[3], user_id: md[4] }
end
token
end
def self.token_from_sourcedid!(sourcedid)
Canvas::Security.decrypt_encrypted_jwt(
Canvas::Security.base64_decode(sourcedid),
signing_secret,
encryption_secret
)
rescue JSON::JWT::InvalidFormat
raise Errors::InvalidSourceId.new("Invalid sourcedid", :sourcedid_invalid)
end
def self.signing_secretView on GitHub (pinned to 1c9f0bb801)