{"record":{"id":"8d1f7195d8fe4d7f","repo":"instructure/canvas-lms","slug":"allocation-rule-not-found-update","errorCode":null,"errorMessage":"Allocation rule not found","messagePattern":"Allocation rule not found","errorType":"exception","errorClass":"GraphQL::ExecutionError","httpStatus":null,"severity":"error","filePath":"app/graphql/mutations/update_allocation_rule.rb","lineNumber":47,"sourceCode":"    validate_feature_flag!(course)\n    verify_authorized_action!(assignment, :update)\n    validate_id_arrays!(input)\n\n    updated_rules = if input[:reciprocal]\n                      update_reciprocal_rules(allocation_rule, input, assignment, course)\n                    else\n                      update_regular_rules(allocation_rule, input, assignment, course)\n                    end\n\n    process_allocation_rules(updated_rules)\n  end\n\n  private\n\n  def get_allocation_rule(rule_id)\n    AllocationRule.active.find(rule_id)\n  rescue ActiveRecord::RecordNotFound\n    raise GraphQL::ExecutionError, I18n.t(\"Allocation rule not found\")\n  end\n\n  def update_reciprocal_rules(original_rule, input, assignment, course)\n    shared_opts = {\n      must_review: input[:must_review],\n      review_permitted: input[:review_permitted],\n      applies_to_assessor: input[:applies_to_assessor]\n    }\n    assess_opts = {\n      assessor_id: input[:assessor_ids].first,\n      assessee_id: input[:assessee_ids].first,\n    }\n    updated_rule = update_rule_fields(original_rule, shared_opts.merge(assess_opts))\n\n    reciprocal_opts = {\n      assessor_id: input[:assessee_ids].first,\n      assessee_id: input[:assessor_ids].first,\n    }","sourceCodeStart":29,"sourceCodeEnd":65,"githubUrl":"https://github.com/instructure/canvas-lms/blob/1c9f0bb8013ed69c4f2efe11fd483025469b7e6c/app/graphql/mutations/update_allocation_rule.rb#L29-L65","documentation":"UpdateAllocationRule#get_allocation_rule looks up an AllocationRule with AllocationRule.active.find(rule_id). ActiveRecord::RecordNotFound is rescued and re-raised as a GraphQL::ExecutionError with the message 'Allocation rule not found'. It is thrown when the id does not match an existing allocation rule, or when the rule exists but is no longer active (soft-deleted).","triggerScenarios":"Calling the updateAllocationRule mutation with an id that (a) does not exist, (b) belongs to a deleted/inactive rule (find is scoped to AllocationRule.active), or (c) is a malformed id that cannot be resolved to a record.","commonSituations":"The rule was deleted by another user between listing and updating; the client cached an old rule id; passing a rule id from a different course/account root; typos or stale references in scripts hitting the GraphQL API.","solutions":["Fetch the current rule id via the allocationRules GraphQL query and confirm it is active before mutating","If the rule is soft-deleted, restore it or create a new rule instead of updating","Verify the id is the AllocationRule's GraphQL/legacy id for the correct course","Retry with a valid active rule id"],"exampleFix":"// before\nmutation { updateAllocationRule(input: {id: \"123\", mustReview: 1}) { ... } }\n// after\n// query first and use the returned active rule id\nquery { course(id: 1) { allocationRules { id } } }\nmutation { updateAllocationRule(input: {id: \"<valid-active-id>\", mustReview: 1}) { ... } }","handlingStrategy":"validation","validationCode":"const rule = await canvasQuery(`query { course(id: $cid) { allocationRules { id } } }`, {cid});\nif (!rule?.allocationRules?.some(r => r.id === inputId)) throw new Error(`Allocation rule ${inputId} is missing or inactive; refresh rule ids before updating`);","typeGuard":"function isActiveRule(rule) { return rule != null && typeof rule.id === 'string' && rule.id.length > 0; }","tryCatchPattern":"try {\n  await updateAllocationRule({ id });\n} catch (e) {\n  if (/Allocation rule not found/.test(e.message)) {\n    // refresh ids / recreate rule\n  } else { throw e; }\n}","preventionTips":["Always resolve rule ids from a fresh allocationRules query, never from cached data","Remember the lookup is scoped to AllocationRule.active — deleted rules will not resolve","Log the rule id and course context when this error occurs to catch cross-course id mixups"],"tags":["graphql","activerecord","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"}