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
- Confirm the group ID exists and workflow_state is 'active' via a prior GraphQL lookup.
- Re-select the parent group in the UI instead of relying on cached IDs.
- Ensure the request is executed on the correct shard for the group.
- 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
- Resolve parent groups through GraphQL Node lookups right before mutation.
- Keep UI selection in sync with group deletions (subscribe or refetch).
- Validate shard/account scope of ids in cross-account tools.
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)
endView on GitHub (pinned to 1c9f0bb801)