instructure/canvas-lms · error · GraphQL::ExecutionError
not found
Error message
not found
What it means
This is a deliberately translated error inside the updateDiscussionTopicParticipant GraphQL mutation. The resolver loads the DiscussionTopic by id, and any ActiveRecord::RecordNotFound (or an id belonging to a non-discussion object, since DiscussionTopic.find uses the ID type) is rescued and re-raised as a GraphQL::ExecutionError with the message "not found". GraphQL clients see it in the errors array rather than as an unhandled exception.
Solutions
- Verify the discussion_topic_id exists and is not deleted: DiscussionTopic.unscoped.find_by(id: ...).
- Ensure the client sends the correctly encoded Relay/legacy id expected by the mutation's ID prepare function.
- In multi-shard environments, use the shard-prefixed id so the record is found on the correct shard.
- Check the acting user has :read permission on the topic, since the same flow can 404/fail when access is lost.
- Handle the errors array in the GraphQL client and prompt the user to refresh/reselect the discussion.
Example fix
// before
updateDiscussionTopicParticipant(input: { discussionTopicId: "17", ... })
// after
// resolve the id through a fresh query first
topic = DiscussionTopic.unscoped.find_by(id: id)
raise "topic missing" unless topic
updateDiscussionTopicParticipant(input: { discussionTopicId: topic.relay_id, ... }) Defensive patterns
Strategy: try-catch
Validate before calling
// before calling the mutation
const topic = await fetchDiscussionTopic(id)
if (!topic) throw new Error(`discussion topic ${id} does not exist`) Type guard
const isTopic = (t) => !!t && typeof t.id === 'string' && t.__typename === 'DiscussionTopic'
Try / catch
try {
await updateDiscussionTopicParticipant(input)
} catch (e) {
if (e.graphQLErrors?.some(g => g.message === 'not found')) {
refreshDiscussionList() // topic likely deleted or id invalid
} else { throw e }
} Prevention
- Always source the topic id from a fresh query, not long-lived client cache.
- Use shard-prefixed ids in multi-shard Canvas deployments.
- Check the user can :read the topic before offering the mutation in UI.
When it happens
Trigger: Calling mutation updateDiscussionTopicParticipant with a discussion_topic_id that does not exist, is soft-deleted, belongs to a different shard, or is a non-topic object whose ID collides in the Relay ID decoding.
Common situations: Clients caching a topic id after the topic was deleted; passing a legacy numeric id instead of the expected base64/Relay id (or vice versa depending on the prepare function); multi-shard setups where the id is not shard-prefixed so Switchman looks it up on the wrong shard.
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/0cfe6807247f5e45.
Report an issue: GitHub.
Appendix: source
Thrown at app/graphql/mutations/update_discussion_topic_participant.rb:40
graphql_name "UpdateDiscussionTopicParticipant"
argument :discussion_topic_id, ID, required: true, prepare: GraphQLHelpers.relay_or_legacy_id_prepare_func("DiscussionEntry")
argument :expanded, Boolean, required: false
argument :has_unread_pinned_entry, Boolean, required: false
argument :preferred_language, Types::PreferredLanguageType, required: false
argument :show_pinned_entries, Boolean, required: false
argument :sort_order, Types::DiscussionSortOrderType, required: false
argument :summary_enabled, Boolean, required: false
field :discussion_topic, Types::DiscussionType, null: false
def resolve(input:)
discussion_topic = DiscussionTopic.find(input[:discussion_topic_id])
raise GraphQL::ExecutionError, "insufficient permission" unless discussion_topic.grants_right?(current_user, session, :read)
discussion_topic.update_or_create_participant(current_user:, **input)
{ discussion_topic: }
rescue ActiveRecord::RecordNotFound
raise GraphQL::ExecutionError, "not found"
end
end
View on GitHub (pinned to 1c9f0bb801)