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
- Grant the user a role with :manage_institutional_tags_edit on the root account (Account > Permissions).
- Check the current permission: root_account.grants_right?(user, session, :manage_institutional_tags_edit) in console.
- Verify the user session/authentication is valid and current_user is the expected account admin.
- 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
- Hide institutional tag editing from users lacking manage_institutional_tags_edit.
- Audit custom account roles so the permission is explicitly granted where needed.
- Use service tokens tied to a permissioned admin user, not anonymous contexts.
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 }
elseView on GitHub (pinned to 1c9f0bb801)