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

Group not found

Error message

Group not found

What it means

MoveOutcomeLinks#get_group! looks up LearningOutcomeGroup.active.find_by(id: input[:group_id]); if no active group matches it raises this ExecutionError. Deleted (soft-deleted/workflow_state != active) or nonexistent groups both produce it.

Solutions

  1. Verify the group_id references an active LearningOutcomeGroup
  2. Re-fetch the outcome group structure to get a current group ID
  3. If the group is globally-scoped, confirm you are using the correct global group ID

Example fix

// before
moveOutcomeLinks(input: { groupId: 88, ... }) // group deleted
// after
moveOutcomeLinks(input: { groupId: 102, ... }) // active group from fresh query
Defensive patterns

Strategy: validation

Validate before calling

// verify the group is active before moving outcomes
const g = await client.query({ query: OUTCOME_GROUP, variables: { id: groupId } });
if (!g.data?.learningOutcomeGroup || g.data.learningOutcomeGroup.workflowState !== 'active') {
  throw new Error(`Outcome group ${groupId} is not active`);
}

Try / catch

try {
  await client.mutate({ mutation: MOVE_OUTCOME_LINKS, variables: { input } });
} catch (e) {
  if (e.message.includes('Group not found')) {
    // refetch the group tree and let the user re-pick a target group
  }
}

Prevention

When it happens

Trigger: Calling moveOutcomeLinks with a group_id that does not exist, refers to a deleted/inactive outcome group, or is on another shard.

Common situations: Stale group IDs in frontend state after a group was deleted; using inactive groups from old links; environment/shard mismatch in multi-tenant installs.

Understand the failure class

Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.

Related errors


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

Appendix: source

Thrown at app/graphql/mutations/move_outcome_links.rb:65

    group.touch_parent_group if outcome_links.any?

    context[:group] = group

    {
      errors:,
      moved_outcome_links: ContentTag.where(id: outcome_links.pluck(:id))
    }
  end

  def self.moved_outcome_link_ids_log_entry(_ids, ctx)
    ctx[:group]
  end

  private

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

      if group.context
        raise GraphQL::ExecutionError, I18n.t("Insufficient permission") unless
          group.context.grants_right?(current_user, session, :manage_outcomes)
      else
        raise GraphQL::ExecutionError, I18n.t("Insufficient permission") unless
          Account.site_admin.grants_right?(current_user, session, :manage_global_outcomes)
      end
    end
  end

  def get_outcome_links(input, context)
    ids = input[:outcome_link_ids].map(&:to_i).uniq
    links = if context
              ContentTag.active.learning_outcome_links.where(
                context:,
                id: ids
              )

View on GitHub (pinned to 1c9f0bb801)