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

  1. 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.
  2. Catch MissingSubAssignmentSubmissionError and return a placeholder/empty payload instead of serializing.
  3. Verify the sub_assignment.id and user_id passed in are correct (the fallback lookup uses Submission.unscoped.find_by(assignment_id:, user_id:)).
  4. 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

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


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)