{"record":{"id":"1d89e547fd7ad72f","repo":"instructure/canvas-lms","slug":"no-assignment-present-for-submission-id-skipping-conditional","errorCode":null,"errorMessage":"No assignment present for submission #{id}; skipping conditional release handler","messagePattern":"No assignment present for submission #(.+?); skipping conditional release handler","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"app/models/submission.rb","lineNumber":2406,"sourceCode":"                         { priority:, strand: },\n                         self)\n\n    assignment&.delay_if_production(strand:)&.multiple_module_actions([user_id], :scored, score)\n  end\n\n  def maybe_queue_conditional_release_grade_change_handler\n    shard.activate do\n      if Account.site_admin.feature_enabled? :mastery_path_submission_trigger_reloaded_evaluation\n        reloaded = Submission.find(id)\n        return unless reloaded.graded? && reloaded.posted?\n      else\n        return unless graded? && posted?\n      end\n\n      if assignment.present? && assignment.queue_conditional_release_grade_change_handler?\n        queue_conditional_release_grade_change_handler\n      elsif assignment.blank?\n        logger.warn(\"No assignment present for submission #{id}; skipping conditional release handler\")\n      end\n    end\n  end\n\n  scope :with_assignment, -> { joins(:assignment).merge(Assignment.active) }\n\n  scope :graded, -> { where(\"(submissions.score IS NOT NULL AND submissions.workflow_state = 'graded') or submissions.excused = true\") }\n  scope :with_sticker, -> { where.not(sticker: nil) }\n  scope :not_submitted_or_graded, -> { where(submission_type: nil).where(\"(submissions.score IS NULL OR submissions.workflow_state <> 'graded') AND submissions.excused IS NOT TRUE\") }\n\n  scope :ungraded, -> { where(grade: nil).preload(:assignment) }\n\n  scope :in_workflow_state, ->(provided_state) { where(workflow_state: provided_state) }\n\n  scope :having_submission, -> { where.not(submissions: { submission_type: nil }) }\n  scope :without_submission, -> { where(submission_type: nil, workflow_state: \"unsubmitted\") }\n  scope :not_placeholder, lambda {\n    active.where(\"submissions.submission_type IS NOT NULL or submissions.excused or submissions.score IS NOT NULL or submissions.workflow_state = 'graded'\")","sourceCodeStart":2388,"sourceCodeEnd":2424,"githubUrl":"https://github.com/instructure/canvas-lms/blob/1c9f0bb8013ed69c4f2efe11fd483025469b7e6c/app/models/submission.rb#L2388-L2424","documentation":"When a submission's grade changes, Canvas enqueues a conditional release (rollout) grade change handler via its assignment. If the submission has no assignment associated (orphaned or deleted record), it logs this warning and skips the handler instead of raising a NoMethodError on nil.","triggerScenarios":"Running conditional-release grade-change callbacks on a Submission whose assignment_id is nil or whose assignment was hard-deleted while the submission survived, with graded?/posted? conditions met so the handler path is reached.","commonSituations":"Data cleanup deleted assignments without cascading submissions; cross-shard or import artifacts producing orphaned submissions; conditional release feature enabled while processing legacy/bad data.","solutions":["Find and clean orphaned submissions: `Submission.where.missing(:assignment)` and remove or restore them","Restore the deleted assignment or nullify/repoint the submission's association","Guard handler scheduling at the caller so submissions without valid assignments are filtered out","If orphaned data is unexpected, audit deletion callbacks to ensure submissions are destroyed with their assignment"],"exampleFix":"// before\nif assignment.present? && assignment.queue_conditional_release_grade_change_handler?\n  queue_conditional_release_grade_change_handler\nend\n\n// after: filter early at the scope/caller level\nscope :with_gradable_assignment, -> { joins(:assignment).merge(Assignment.active) }\n# then only enqueue handlers for submissions in that scope","handlingStrategy":"type-guard","validationCode":"sub = Submission.find(id)\nif sub.assignment.blank?\n  Rails.logger.warn(\"submission #{sub.id} has no assignment; skipping\")\nend","typeGuard":"def gradeable_submission?(submission)\n  submission.graded? && submission.posted? && submission.assignment.present?\nend","tryCatchPattern":null,"preventionTips":["Destroy submissions together with their assignments (dependent: :destroy)","Filter handler scheduling with joins(:assignment) so orphaned submissions are skipped","Monitor logs for this warning as an orphaned-data signal and clean records"],"tags":["ruby","rails","conditional-release","orphaned-records"],"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"}