instructure/canvas-lms · error · GraphQL::ExecutionError
Assignment group category id and discussion topic group…
Error message
Assignment group category id and discussion topic group category id do not match
What it means
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.
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.
Example fix
// before
updateDiscussionTopic(input: {id: t, assignment: {groupCategoryId: "42"}})
// after
updateDiscussionTopic(input: {id: t, assignment: {groupCategoryId: topic.groupSet.id}}) Defensive patterns
Strategy: validation
Validate before calling
if (input.assignment?.groupCategoryId && topic.groupSet && input.assignment.groupCategoryId !== topic.groupSet.id) {
throw new Error('Group category must match the topic group set');
} Type guard
function groupCategoriesMatch(assignmentInput, topic) {
return !assignmentInput.groupCategoryId || String(assignmentInput.groupCategoryId) === String(topic.groupCategoryId);
} Try / catch
try {
await updateDiscussionTopic(...);
} catch (e) {
if (e.message.includes('group category id')) {
// resync group set then retry
await updateTopicGroupSet();
await updateDiscussionTopic(...);
}
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Group category IDs do not match
- assignment not found
- Assignments under moderation cannot be posted before grades…
- Error posting assignment grades
- not found
AI-assisted analysis of instructure/canvas-lms@1c9f0bb801 (2026-09-15).
Data as JSON: /api/errors/defd50001ac25851.
Report an issue: GitHub.
Appendix: source
Thrown at app/graphql/mutations/update_discussion_topic.rb:244
end
discussion_topic.editor = current_user
return errors_for(discussion_topic) unless discussion_topic.save!
if input.key?(:ungraded_discussion_overrides)
overrides = input[:ungraded_discussion_overrides] || []
update_ungraded_discussion(discussion_topic, overrides)
end
discussion_topic.assignment = assignment_result[:assignment] if assignment_result && assignment_result[:assignment]
{
discussion_topic:
}
rescue ActiveRecord::RecordNotFound
raise GraphQL::ExecutionError, "not found"
rescue ArgumentError
raise GraphQL::ExecutionError, "Assignment group category id and discussion topic group category id do not match"
end
end
def set_discussion_assignment_association(assignment_params, discussion_topic)
# Determine if the assignment is being deleted
is_deleting_assignment = assignment_params.key?(:set_assignment) && !assignment_params[:set_assignment]
if is_deleting_assignment && !discussion_topic&.assignment.nil?
assignment = discussion_topic.assignment
if assignment.has_sub_assignments
Checkpoints::DiscussionCheckpointDeleterService.call(
discussion_topic:
)
end
discussion_topic.assignment = nil
assignment.discussion_topic = nilView on GitHub (pinned to 1c9f0bb801)