instructure/canvas-lms · error · GraphQL::ExecutionError
not found
Error message
not found
What it means
updateInstitutionalTagArchivedState loads the tag with InstitutionalTag.where(root_account_id: root_account.id).find_by(id:) — this variant does not filter on workflow_state, but still requires the record to exist under the current root account. If find_by returns nil it raises "not found". The resolver's trailing rescue of ActiveRecord::RecordNotFound provides the same message for any RecordNotFound raised later (e.g. during undestroy).
Solutions
- Confirm the tag exists under this root account: InstitutionalTag.where(root_account_id: root_account.id).find_by(id:) in console.
- Verify the Relay id is encoded for the InstitutionalTag type, not another type.
- Check the request resolves to the same root account that owns the tag.
- Handle the GraphQL errors entry and refresh the tag list before retrying.
Example fix
// before
updateInstitutionalTagArchivedState(input: { id: otherAccountTagId, archived: true })
// after
const tag = tagsByAccount[rootAccountId]?.find(t => t.id === tagId)
if (!tag) throw new Error('tag not found for this account')
updateInstitutionalTagArchivedState(input: { id: tagRelayId, archived: true }) Defensive patterns
Strategy: validation
Validate before calling
// confirm the tag exists under this account before archiving
const tags = await fetchAllInstitutionalTags(rootAccountId) // includes archived
if (!tags.some(t => t.id === tagId)) throw new Error(`tag ${tagId} not found for this account`) Type guard
const isInstitutionalTag = (t) => !!t && t.__typename === 'InstitutionalTag'
Try / catch
try {
await updateInstitutionalTagArchivedState(input)
} catch (e) {
if (e.graphQLErrors?.some(g => g.message === 'not found')) {
await refreshTagList() // wrong account or bad relay id
} else { throw e }
} Prevention
- Encode ids with the InstitutionalTag relay type, never reuse other types' ids.
- Verify the tag belongs to the resolving root account before mutating.
- Refresh the tag list (including archived) before retrying archive state changes.
When it happens
Trigger: Passing an id that doesn't exist at all, belongs to a different root account, or is not decodable as an InstitutionalTag Relay id; a RecordNotFound raised from tag.undestroy when an unarchived state conflicts.
Common situations: Archiving an already-archived tag with a stale id; cross-account ids copied between environments; Relay id prepared for a different object type so the resolved raw id does not match any InstitutionalTag row.
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/3d02bc46292090d4.
Report an issue: GitHub.
Appendix: source
Thrown at app/graphql/mutations/update_institutional_tag_archived_state.rb:39
# NOTE: Depends on InstitutionalTag and InstitutionalTagAssociation models
module Mutations
class UpdateInstitutionalTagArchivedState < BaseMutation
argument :archived, Boolean, required: true
argument :id,
ID,
required: true,
prepare: GraphQLHelpers.relay_or_legacy_id_prepare_func("InstitutionalTag")
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).find_by(id: input[:id])
raise GraphQL::ExecutionError, "not found" unless tag
input[:archived] ? tag.destroy : tag.undestroy
{ institutional_tag: tag }
rescue ActiveRecord::RecordInvalid
errors_for(tag)
rescue ActiveRecord::RecordNotFound
raise GraphQL::ExecutionError, "not found"
end
end
end
View on GitHub (pinned to 1c9f0bb801)