{"record":{"id":"6be9d6a28f9ca7ca","repo":"instructure/canvas-lms","slug":"group-not-found-update-learning-outcome","errorCode":null,"errorMessage":"Group not found","messagePattern":"Group not found","errorType":"exception","errorClass":"GraphQL::ExecutionError","httpStatus":null,"severity":"warning","filePath":"app/graphql/mutations/update_learning_outcome_group.rb","lineNumber":53,"sourceCode":"    check_user_permissions\n\n    @outcome_group.saving_user = current_user\n    if @outcome_group.update(attributes(input))\n      if input[:parent_outcome_group_id] && input[:parent_outcome_group_id] != @outcome_group.learning_outcome_group_id\n        new_parent_group = get_parent_group(input[:parent_outcome_group_id])\n        raise GraphQL::ExecutionError, I18n.t(\"Could not update parent group\") unless new_parent_group.adopt_outcome_group(@outcome_group)\n      end\n      { learning_outcome_group: @outcome_group }\n    else\n      errors_for(@outcome_group)\n    end\n  end\n\n  private\n\n  def get_group(id)\n    LearningOutcomeGroup.active.find_by(id:).tap do |group|\n      raise GraphQL::ExecutionError, I18n.t(\"Group not found\") unless group\n    end\n  end\n\n  def get_parent_group(id)\n    LearningOutcomeGroup.for_context(@outcome_group.context).active.find_by(id:).tap do |group|\n      raise GraphQL::ExecutionError, I18n.t(\"Parent group not found in this context\") unless group\n    end\n  end\n\n  def check_user_permissions\n    raise GraphQL::ExecutionError, I18n.t(\"Insufficient permissions\") unless can_manage_outcomes\n  end\n\n  def can_manage_outcomes\n    if @outcome_group.context\n      @outcome_group.context.grants_right?(current_user, session, :manage_outcomes)\n    else\n      Account.site_admin.grants_right?(current_user, session, :manage_global_outcomes)","sourceCodeStart":35,"sourceCodeEnd":71,"githubUrl":"https://github.com/instructure/canvas-lms/blob/1c9f0bb8013ed69c4f2efe11fd483025469b7e6c/app/graphql/mutations/update_learning_outcome_group.rb#L35-L71","documentation":"UpdateLearningOutcomeGroup#get_group raises this when LearningOutcomeGroup.active.find_by(id:) returns nil for the group id supplied in the mutation. It signals the target group to update does not exist (or is not active).","triggerScenarios":"Calling updateLearningOutcomeGroup with input.id referencing a deleted/inactive group, a nonexistent id, or an id on a different shard.","commonSituations":"Group soft-deleted (workflow_state != active) so find_by(id:) with .active scope misses it; stale client cache; id from another environment; typo in the id.","solutions":["Verify the id exists and is active: LearningOutcomeGroup.active.find_by(id: id) in console.","Check the group's workflow_state — soft-deleted groups won't match the .active scope.","Refresh the group id from the API instead of using a cached value.","Confirm you are querying the correct shard/database."],"exampleFix":"// before\nupdateLearningOutcomeGroup(input: {id: \"999\"}) { ... } // deleted group\n// after\n# const group = await fetchOutcomeGroup(id); if (!group) showNotFound();\nupdateLearningOutcomeGroup(input: {id: \"12\"}) { ... }","handlingStrategy":"validation","validationCode":"const group = await gql(FETCH_OUTCOME_GROUP, { id });\nif (!group?.learningOutcomeGroup) throw new Error(`group ${id} not found`);","typeGuard":"function groupExists(data) { return data?.learningOutcomeGroup != null; }","tryCatchPattern":"try {\n  await gql(UPDATE_LEARNING_OUTCOME_GROUP, { id, ...attrs });\n} catch (e) {\n  if (e.message === 'Group not found') { /* remove stale item from UI list */ }\n  else throw e;\n}","preventionTips":["Refresh group lists after deletions instead of trusting cache","Remember .active scope excludes soft-deleted groups","Validate ids against the correct shard"],"tags":["graphql","outcome-groups","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"}