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

not authorized

Error message

not authorized

What it means

The updateInstitutionalTag mutation requires the acting user to hold the :manage_institutional_tags_edit right on the domain root account. When grants_right? returns false, it raises GraphQL::ExecutionError "not authorized" before any tag lookup occurs.

Solutions

  1. Grant the user a role with :manage_institutional_tags_edit on the root account (Account > Permissions).
  2. Check the current permission: root_account.grants_right?(user, session, :manage_institutional_tags_edit) in console.
  3. Verify the user session/authentication is valid and current_user is the expected account admin.
  4. Hide the editing UI for users without the permission so the mutation is not invoked.
Defensive patterns

Strategy: validation

Validate before calling

// check the user's permission before invoking
const perms = await fetchMyPermissions(rootAccountId)
if (!perms.includes('manage_institutional_tags_edit')) throw new Error('user not authorized')

Try / catch

try {
  await updateInstitutionalTag(input)
} catch (e) {
  if (e.graphQLErrors?.some(g => g.message === 'not authorized')) {
    showAccessDeniedNotice()
  } else { throw e }
}

Prevention

When it happens

Trigger: Any updateInstitutionalTag call where the current user is a student/teacher/plain admin lacking the manage_institutional_tags_edit permission, the user's session has expired to an unauthenticated role, or the permission was disabled at the account role level.

Common situations: Role permission edits removing the right from custom admin roles; calling the mutation from a background job/script with no user context; users assuming admin status implies this specific granular permission.

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/1b158f6031abcbaf. Report an issue: GitHub.

Appendix: source

Thrown at app/graphql/mutations/update_institutional_tag.rb:41

module Mutations
  class UpdateInstitutionalTag < BaseMutation
    argument :category_id,
             ID,
             required: false,
             prepare: GraphQLHelpers.relay_or_legacy_id_prepare_func("InstitutionalTagCategory")
    argument :description, String, required: false
    argument :id,
             ID,
             required: true,
             prepare: GraphQLHelpers.relay_or_legacy_id_prepare_func("InstitutionalTag")
    argument :name, String, required: false

    field :institutional_tag, Types::InstitutionalTagType, null: true

    def resolve(input:)
      root_account = context[:domain_root_account]
      raise GraphQL::ExecutionError, "feature flag is disabled" unless root_account.feature_enabled?(:institutional_tags)
      raise GraphQL::ExecutionError, "not authorized" unless root_account.grants_right?(current_user, session, :manage_institutional_tags_edit)

      tag = InstitutionalTag.where(root_account_id: root_account.id, workflow_state: "active").find_by(id: input[:id])
      raise GraphQL::ExecutionError, "not found" unless tag

      attrs = {}
      attrs[:name] = input[:name] if input.key?(:name)
      attrs[:description] = input[:description] if input.key?(:description)

      if input.key?(:category_id)
        category = root_account.institutional_tag_categories.where(workflow_state: "active").find_by(id: input[:category_id])
        raise GraphQL::ExecutionError, "not found" unless category

        attrs[:category_id] = category.id
      end

      if tag.update(attrs)
        { institutional_tag: tag }
      else

View on GitHub (pinned to 1c9f0bb801)