instructure/canvas-lms · error · GraphQL::ExecutionError
Record not found
Error message
Record not found
What it means
UpdateCommentBankItem#resolve loads the CommentBankItem by id; when ActiveRecord::RecordNotFound bubbles out of resolve it is rescued at the end of the method and re-raised as GraphQL::ExecutionError 'Record not found'. The item either does not exist, was deleted, or is not visible to the current user's account scope.
Solutions
- Re-query commentBankItems for the current user to get a valid id
- Confirm the item was not deleted (CommentBankItem.active/exists?) and recreate it if needed
- Ensure the id belongs to the same account/user context as the caller
- Drop the update if the item was intentionally deleted
Example fix
// before
mutation { updateCommentBankItem(input: {id: "42", comment: "hi"}) { ... } }
// after
query { commentBankItemsConnection { nodes { id } } }
mutation { updateCommentBankItem(input: {id: "<valid-id>", comment: "hi"}) { ... } } Defensive patterns
Strategy: validation
Validate before calling
const items = await canvasQuery(`query { commentBankItemsConnection { nodes { id } } }`);
if (!items?.commentBankItemsConnection?.nodes.some(i => i.id === inputId)) throw new Error(`Comment bank item ${inputId} not found for this user; refresh list`); Type guard
function itemExists(items, id) { return Array.isArray(items) && items.some(i => i?.id === id); } Try / catch
try {
await updateCommentBankItem({ id, comment });
} catch (e) {
if (/Record not found/.test(e.message)) {
// drop the item from the cache or recreate it
} else { throw e; }
} Prevention
- Invalidate local comment-bank caches when items are deleted
- Scope ids to the current user/account — items are account/user scoped
- Treat 'Record not found' as a soft-delete signal, not a bug
When it happens
Trigger: Calling updateCommentBankItem with an id of a deleted comment bank item, an id from another user/account, or a nonexistent id.
Common situations: Items deleted via UI while a client still holds their id; comment bank items are account-scoped so cross-account ids 404; stale caches in frontends after cleanup jobs.
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/24972ffb46d0e9b6.
Report an issue: GitHub.
Appendix: source
Thrown at app/graphql/mutations/update_comment_bank_item.rb:40
graphql_name "UpdateCommentBankItem"
argument :comment, String, required: true
argument :id, ID, required: true, prepare: GraphQLHelpers.relay_or_legacy_id_prepare_func("CommentBankItem")
field :comment_bank_item, Types::CommentBankItemType, null: true
def resolve(input:)
record = CommentBankItem.active.find(input[:id])
verify_authorized_action!(record, :update)
record.comment = input[:comment]
return errors_for(record) unless record.save
{ comment_bank_item: record }
rescue ActiveRecord::RecordNotFound
raise GraphQL::ExecutionError, I18n.t("Record not found")
end
end
View on GitHub (pinned to 1c9f0bb801)