{"record":{"id":"defd50001ac25851","repo":"instructure/canvas-lms","slug":"assignment-group-category-id-and-discussion-topic-group","errorCode":null,"errorMessage":"Assignment group category id and discussion topic group category id do not match","messagePattern":"Assignment group category id and discussion topic group category id do not match","errorType":"exception","errorClass":"GraphQL::ExecutionError","httpStatus":null,"severity":"error","filePath":"app/graphql/mutations/update_discussion_topic.rb","lineNumber":244,"sourceCode":"    end\n\n    discussion_topic.editor = current_user\n    return errors_for(discussion_topic) unless discussion_topic.save!\n\n    if input.key?(:ungraded_discussion_overrides)\n      overrides = input[:ungraded_discussion_overrides] || []\n      update_ungraded_discussion(discussion_topic, overrides)\n    end\n\n    discussion_topic.assignment = assignment_result[:assignment] if assignment_result && assignment_result[:assignment]\n\n    {\n      discussion_topic:\n    }\n  rescue ActiveRecord::RecordNotFound\n    raise GraphQL::ExecutionError, \"not found\"\n  rescue ArgumentError\n    raise GraphQL::ExecutionError, \"Assignment group category id and discussion topic group category id do not match\"\n  end\nend\n\ndef set_discussion_assignment_association(assignment_params, discussion_topic)\n  # Determine if the assignment is being deleted\n  is_deleting_assignment = assignment_params.key?(:set_assignment) && !assignment_params[:set_assignment]\n\n  if is_deleting_assignment && !discussion_topic&.assignment.nil?\n    assignment = discussion_topic.assignment\n\n    if assignment.has_sub_assignments\n      Checkpoints::DiscussionCheckpointDeleterService.call(\n        discussion_topic:\n      )\n    end\n\n    discussion_topic.assignment = nil\n    assignment.discussion_topic = nil","sourceCodeStart":226,"sourceCodeEnd":262,"githubUrl":"https://github.com/instructure/canvas-lms/blob/1c9f0bb8013ed69c4f2efe11fd483025469b7e6c/app/graphql/mutations/update_discussion_topic.rb#L226-L262","documentation":"UpdateDiscussionTopic#resolve rescues ArgumentError raised deeper in the assignment/group-category handling (see validate_and_remove_group_category_id) and re-raises it as GraphQL::ExecutionError with the message \"Assignment group category id and discussion topic group category id do not match\". It signals an attempt to attach an assignment whose group set differs from the topic's group set.","triggerScenarios":"Passing assignment: {groupCategoryId: X} in updateDiscussionTopic where the topic already has group_category_id Y != X, e.g. switching a group discussion's group set while also creating/updating its assignment in one call.","commonSituations":"Instructors moving a discussion to a different student group set; LTI tools submitting assignment payloads with a default group category; import/migration reusing stale group_category_id values; frontend form caching the old group set after topic edit.","solutions":["Align the payload's group_category_id with the topic's existing group_category_id, or clear the topic's group set first.","Split into two mutations: first update the topic's group set, then update the assignment.","Omit group_category_id from the assignment input when it should inherit the topic's group set.","Validate ids client-side against the topic's groupSet before submit."],"exampleFix":"// before\nupdateDiscussionTopic(input: {id: t, assignment: {groupCategoryId: \"42\"}})\n// after\nupdateDiscussionTopic(input: {id: t, assignment: {groupCategoryId: topic.groupSet.id}})","handlingStrategy":"validation","validationCode":"if (input.assignment?.groupCategoryId && topic.groupSet && input.assignment.groupCategoryId !== topic.groupSet.id) {\n  throw new Error('Group category must match the topic group set');\n}","typeGuard":"function groupCategoriesMatch(assignmentInput, topic) {\n  return !assignmentInput.groupCategoryId || String(assignmentInput.groupCategoryId) === String(topic.groupCategoryId);\n}","tryCatchPattern":"try {\n  await updateDiscussionTopic(...);\n} catch (e) {\n  if (e.message.includes('group category id')) {\n    // resync group set then retry\n    await updateTopicGroupSet();\n    await updateDiscussionTopic(...);\n  }\n}","preventionTips":["Mirror the topic's group set into assignment forms by default","Split topic group-set changes from assignment updates into separate calls","Compare group category IDs as strings end-to-end"],"tags":["graphql","assignments","group-categories"],"backgroundTag":"invalid-argument-value","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"}