{"record":{"id":"ed3db926e227245f","repo":"instructure/canvas-lms","slug":"assignment-not-found-create-allocation-rule","errorCode":null,"errorMessage":"Assignment not found","messagePattern":"Assignment not found","errorType":"exception","errorClass":"GraphQL::ExecutionError","httpStatus":null,"severity":"error","filePath":"app/graphql/mutations/create_allocation_rule.rb","lineNumber":78,"sourceCode":"      target_id = input[:applies_to_assessor] ? input[:assessor_ids].first : input[:assessee_ids].first\n      subjects = input[:applies_to_assessor] ? input[:assessee_ids] : input[:assessor_ids]\n\n      subjects.each do |subject_id|\n        opts = {\n          assessor_id: input[:applies_to_assessor] ? target_id : subject_id,\n          assessee_id: input[:applies_to_assessor] ? subject_id : target_id\n        }\n        allocation_rules << create_or_find_new_rule(assignment, course, opts.merge(shared_opts))\n      end\n    end\n\n    allocation_rules\n  end\n\n  def get_assignment(assignment_id)\n    Assignment.active.find(assignment_id)\n  rescue ActiveRecord::RecordNotFound\n    raise GraphQL::ExecutionError, I18n.t(\"Assignment not found\")\n  end\nend\n","sourceCodeStart":60,"sourceCodeEnd":81,"githubUrl":"https://github.com/instructure/canvas-lms/blob/1c9f0bb8013ed69c4f2efe11fd483025469b7e6c/app/graphql/mutations/create_allocation_rule.rb#L60-L81","documentation":"create_allocation_rule#get_assignment looks up Assignment.active.find(assignment_id); if no active assignment matches, ActiveRecord::RecordNotFound is rescued and re-raised as 'Assignment not found'. Deleted/concluded (non-active) assignments are treated as nonexistent.","triggerScenarios":"Calling createAllocationRule with an assignmentId that is deleted,soft-deleted, on a different shard, or a non-assignment id; also plain nonexistent ids.","commonSituations":"Client cached an assignment id that was later deleted; id passed belongs to a quiz-lti assignment not in the active scope; cross-shard id format mismatch.","solutions":["Verify the assignment id exists and its workflow_state is active (Assignment.active scope)","Re-fetch assignment ids from the API instead of using cached ones","Check you are passing a valid Assignment relay/legacy id on the correct shard","If the assignment was deleted, restore it or choose another assignment"],"exampleFix":"// before\ncreateAllocationRule(input: { assignmentId: \"12\" }) // assignment deleted\n// after\n// resolve fresh id first:\nassignment = course.assignments.active.find { |a| a.name == \"HW1\" }\ncreateAllocationRule(input: { assignmentId: assignment.relay_id })","handlingStrategy":"validation","validationCode":"const asg = await canvas.get(`/api/v1/courses/${courseId}/assignments/${assignmentId}`)\nif (!asg || asg.deleted_at) throw new Error('assignment missing or deleted')","typeGuard":"function isActiveAssignment(a) { return a != null && a.id != null && a.workflow_state === 'published' && !a.deleted_at }","tryCatchPattern":"try {\n  await client.mutate({ mutation: CREATE_ALLOCATION_RULE, variables: { assignmentId } })\n} catch (e) {\n  if (e.message.includes('Assignment not found')) {\n    assignmentId = await refetchActiveAssignmentId(courseId)\n    // retry once with fresh id\n  } else throw e\n}","preventionTips":["Always resolve assignment ids fresh from the assignments API","Filter out deleted/concluded assignments client-side","Use consistent id formats (legacy numeric vs relay) per endpoint","Watch for cross-shard ids when multi-shard setups are in play"],"tags":["graphql","mutation","assignment","record-not-found"],"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"}