instructure/canvas-lms · error · MissingSubAssignmentSubmissionError
Submission is missing for SubAssignment #
Error message
Submission is missing for SubAssignment #{sub_assignment.id} and user #{user_id} What it means
Checkpoints::SubAssignmentSubmissionSerializer resolves the submission to serialize for a sub-assignment (checkpoint) and user. If the scoped sub_assignment_submission is absent, it falls back to any Submission ever created for that sub-assignment/user; when none exists at all, it raises MissingSubAssignmentSubmissionError. Checkpoint assignments assume a submission shell exists for every relevant student.
Solutions
- Ensure a submission exists: create one (e.g. submission = sub_assignment.submissions.build(user_id: user_id); submission.save!) or have the student open the assignment before serializing.
- Catch MissingSubAssignmentSubmissionError and return a placeholder/empty payload instead of serializing.
- Verify the sub_assignment.id and user_id passed in are correct (the fallback lookup uses Submission.unscoped.find_by(assignment_id:, user_id:)).
- If records were lost in a copy/import, rebuild submissions for affected users via backfill script or re-copy the course.
Example fix
// before Checkpoints::SubAssignmentSubmissionSerializer.new(sub_assignment, user_id).as_json # => MissingSubAssignmentSubmissionError // after unless Submission.unscoped.exists?(assignment_id: sub_assignment.id, user_id: user_id) sub_assignment.submissions.create!(user_id: user_id) end Checkpoints::SubAssignmentSubmissionSerializer.new(sub_assignment, user_id).as_json
Defensive patterns
Strategy: try-catch
Validate before calling
unless Submission.unscoped.exists?(assignment_id: sub_assignment.id, user_id: user_id) sub_assignment.submissions.create!(user_id: user_id) end
Type guard
def submission_exists?(sub_assignment, user_id) Submission.unscoped.exists?(assignment_id: sub_assignment.id, user_id: user_id) end
Try / catch
begin
serializer.as_json
rescue Checkpoints::MissingSubAssignmentSubmissionError => e
Rails.logger.info(e.message)
{ submission: nil }
end Prevention
- Only serialize checkpoint submissions for students actually assigned to the sub-assignment.
- Backfill submission records after course copies/imports.
- Treat a missing submission as 'not started' rather than an error in API responses.
When it happens
Trigger: Serialize a checkpoint sub-assignment submission for a user who has no submission record for that sub_assignment id (student never started, submission never created, or wrong assignment_id/user_id passed).
Common situations: Requesting grades for a checkpoint student before they access the assignment; course copies where submission records were not migrated; serializer invoked for a user not actually assigned to the sub-assignment; checks-based (checkpoints) assignments with missing seed submissions.
Understand the failure class
Background: Record Not Found Errors: "not found", RecordNotFound, and "was not found" — what they mean and how to fix them — this error's family across 28 libraries.
Related errors
- Submission is missing for PeerReviewSubAssignment
- Assignment overrides are not allowed in the parent…
- Can't create media submission without media object
- Cannot set # in the parent assignment for checkpoints.
- Checkpoint '# ' not found
AI-assisted analysis of instructure/canvas-lms@1c9f0bb801 (2026-09-15).
Data as JSON: /api/errors/b7c17924b85dfdfb.
Report an issue: GitHub.
Appendix: source
Thrown at app/serializers/checkpoints/sub_assignment_submission_serializer.rb:52
result
end
{
has_active_submissions: user_has_active_sub_submissions,
submissions: submissions || []
}
end
def self.find_single_sub_assignment_submission(sub_assignment, user_id)
sub_assignment_submission = sub_assignment.submissions.find_by(user_id:)
if sub_assignment_submission.present?
sub_assignment_submission
else
any_submission_ever = Submission.unscoped.find_by(assignment_id: sub_assignment.id, user_id:)
if any_submission_ever.nil?
raise MissingSubAssignmentSubmissionError, "Submission is missing for SubAssignment #{sub_assignment.id} and user #{user_id}"
else
nil
end
end
end
end
View on GitHub (pinned to 1c9f0bb801)