instructure/canvas-lms · error · GraphQL::ExecutionError

Group not found

Error message

Group not found

What it means

CreateLearningOutcomeGroup#get_group looks up LearningOutcomeGroup.active.find_by(id:) and raises 'Group not found' when nil. Like error 151, only active (non-deleted) groups count; missing, deleted, or cross-shard IDs all fail.

Solutions

  1. Confirm the group ID exists and workflow_state is 'active' via a prior GraphQL lookup.
  2. Re-select the parent group in the UI instead of relying on cached IDs.
  3. Ensure the request is executed on the correct shard for the group.
  4. Omit the parent id only if the mutation supports root-level creation for your context; otherwise always pass a verified id.

Example fix

// before
await gql(createLearningOutcomeGroup, { input: { parentGroupId: cachedId } })
// after
const parent = await gql(getOutcomeGroup, { id: cachedId })
if (!parent || parent.workflowState !== 'active') throw new Error('Pick a valid parent group')
await gql(createLearningOutcomeGroup, { input: { parentGroupId: cachedId } })
Defensive patterns

Strategy: validation

Validate before calling

const parent = groupId ? await gql(GET_OUTCOME_GROUP, { id: groupId }) : null
if (groupId && (!parent || parent.workflowState !== 'active')) throw new Error('parent group not found')

Type guard

function isResolvableActiveGroup(g) { return g != null && g.workflowState === 'active' }

Try / catch

try {
  await gql(CREATE_OUTCOME_GROUP, { input })
} catch (e) {
  if (e.message === 'Group not found') openGroupPicker()
  else throw e
}

Prevention

When it happens

Trigger: Calling createLearningOutcomeGroup with parent_outcome_group_id pointing to a nonexistent, soft-deleted, or other-root-account group; omitting the id when the mutation requires nesting under an existing group.

Common situations: UI kept a stale parent group after deletion; syncing groups across environments; passing a course-level group ID where an account-level one is expected.

Understand the failure class

Background: Record Not Found Errors: "not found", RecordNotFound, and "was not found" — what they mean and how to fix them — this error's family across 28 libraries.

Related errors


AI-assisted analysis of instructure/canvas-lms@1c9f0bb801 (2026-09-15). Data as JSON: /api/errors/53a7e9b6ca568cfa. Report an issue: GitHub.

Appendix: source

Thrown at app/graphql/mutations/create_learning_outcome_group.rb:49

  def resolve(input:)
    @outcome_group = get_group(input[:id])

    check_user_permissions

    @child_outcome_group = @outcome_group.child_outcome_groups.build(attributes(input))
    @child_outcome_group.saving_user = current_user
    if @child_outcome_group.save
      { learning_outcome_group: @child_outcome_group }
    else
      errors_for(@child_outcome_group)
    end
  end

  private

  def get_group(id)
    LearningOutcomeGroup.active.find_by(id:).tap do |group|
      raise GraphQL::ExecutionError, I18n.t("Group not found") unless group
    end
  end

  def check_user_permissions
    raise GraphQL::ExecutionError, I18n.t("Insufficient permissions") unless can_manage_outcomes
  end

  def can_manage_outcomes
    if @outcome_group.context
      @outcome_group.context.grants_right?(current_user, session, :manage_outcomes)
    else
      Account.site_admin.grants_right?(current_user, session, :manage_global_outcomes)
    end
  end

  def attributes(input)
    input.to_h.slice(:title, :description, :vendor_guid)
  end

View on GitHub (pinned to 1c9f0bb801)