{"record":{"id":"b7c17924b85dfdfb","repo":"instructure/canvas-lms","slug":"submission-is-missing-for-subassignment-sub-assignment-id","errorCode":null,"errorMessage":"Submission is missing for SubAssignment #{sub_assignment.id} and user #{user_id}","messagePattern":"Submission is missing for SubAssignment #(.+?) and user #(.+?)","errorType":"exception","errorClass":"MissingSubAssignmentSubmissionError","httpStatus":null,"severity":"error","filePath":"app/serializers/checkpoints/sub_assignment_submission_serializer.rb","lineNumber":52,"sourceCode":"      result\n    end\n\n    {\n      has_active_submissions: user_has_active_sub_submissions,\n      submissions: submissions || []\n    }\n  end\n\n  def self.find_single_sub_assignment_submission(sub_assignment, user_id)\n    sub_assignment_submission = sub_assignment.submissions.find_by(user_id:)\n\n    if sub_assignment_submission.present?\n      sub_assignment_submission\n    else\n      any_submission_ever = Submission.unscoped.find_by(assignment_id: sub_assignment.id, user_id:)\n\n      if any_submission_ever.nil?\n        raise MissingSubAssignmentSubmissionError, \"Submission is missing for SubAssignment #{sub_assignment.id} and user #{user_id}\"\n      else\n        nil\n      end\n    end\n  end\nend\n","sourceCodeStart":34,"sourceCodeEnd":59,"githubUrl":"https://github.com/instructure/canvas-lms/blob/1c9f0bb8013ed69c4f2efe11fd483025469b7e6c/app/serializers/checkpoints/sub_assignment_submission_serializer.rb#L34-L59","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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."],"exampleFix":"// before\nCheckpoints::SubAssignmentSubmissionSerializer.new(sub_assignment, user_id).as_json\n# => MissingSubAssignmentSubmissionError\n\n// after\nunless Submission.unscoped.exists?(assignment_id: sub_assignment.id, user_id: user_id)\n  sub_assignment.submissions.create!(user_id: user_id)\nend\nCheckpoints::SubAssignmentSubmissionSerializer.new(sub_assignment, user_id).as_json","handlingStrategy":"try-catch","validationCode":"unless Submission.unscoped.exists?(assignment_id: sub_assignment.id, user_id: user_id)\n  sub_assignment.submissions.create!(user_id: user_id)\nend","typeGuard":"def submission_exists?(sub_assignment, user_id)\n  Submission.unscoped.exists?(assignment_id: sub_assignment.id, user_id: user_id)\nend","tryCatchPattern":"begin\n  serializer.as_json\nrescue Checkpoints::MissingSubAssignmentSubmissionError => e\n  Rails.logger.info(e.message)\n  { submission: nil }\nend","preventionTips":["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."],"tags":["checkpoints","sub-assignment","serializer","submission"],"backgroundTag":"record-not-found","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"}