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

Insufficient permissions

Error message

Insufficient permissions

What it means

CreateLearningOutcomeGroup#check_user_permissions raises 'Insufficient permissions' unless can_manage_outcomes. can_manage_outcomes checks @outcome_group.context.grants_right?(current_user, session, :manage_outcomes); when the group has no context it falls back to site-admin manage rights. So the caller must hold :manage_outcomes in the group's context.

Solutions

  1. Run the mutation as a user with :manage_outcomes on the target group's context (usually an account admin).
  2. Check RoleOverride/permission settings for the user's role in that account and enable 'Manage Learning Outcomes' if appropriate.
  3. Target a group whose context matches where the user has rights (course group for teachers).
  4. Pre-flight the permission via GraphQL permissions fields on the context before calling the mutation.

Example fix

// before
await gql(createLearningOutcomeGroupMutation, { input })
// after
const perms = await gql(groupPermissionsQuery, { groupId })
if (!perms.manageOutcomes) showNoPermissionToast()
else await gql(createLearningOutcomeGroupMutation, { input })
Defensive patterns

Strategy: validation

Validate before calling

const perms = await gql(GROUP_MANAGE_PERMS, { groupId })
if (!perms.manageOutcomes) throw new Error('requires manage_outcomes on the group context')

Try / catch

try {
  await gql(CREATE_OUTCOME_GROUP, { input })
} catch (e) {
  if (e.message === 'Insufficient permissions') showNoManageOutcomesNotice()
  else throw e
}

Prevention

When it happens

Trigger: Calling createLearningOutcomeGroup as a teacher in a course where the account restricts outcome management to admins; a sub-account admin operating on a group owned by the root account; unauthenticated requests (context grants nothing).

Common situations: Account-level 'manage outcomes' feature flag or role override turned off for the user's role; writing to a root-account group from a course-scoped tool; using a token that lost its admin role after rotation.

Understand the failure class

Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.

Related errors


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

Appendix: source

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

    @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
end

View on GitHub (pinned to 1c9f0bb801)