instructure/canvas-lms · error · GraphQL::ExecutionError
Unable to find ConversationMessage
Error message
Unable to find ConversationMessage
What it means
GraphQL::ExecutionError raised in the rescue ActiveRecord::RecordNotFound branch of Mutations::DeleteConversationMessages#resolve. It fires when ConversationMessage.preload(:conversation).find(input[:ids]) cannot find one of the requested ids (deleted, wrong shard, or never existed).
Solutions
- Verify the message ids exist (ConversationMessage.exists?) before calling the mutation
- Refresh stale client state after deletes instead of reusing cached ids
- Ensure ids are passed as valid relay/legacy ids per the argument's prepare function
- Check you are operating on the correct shard/root account
Example fix
// before deleteConversationMessages(ids: ["99999"]) // already deleted // after const ids = cachedIds.filter(id => messageExists(id)) deleteConversationMessages(ids)
Defensive patterns
Strategy: validation
Validate before calling
const missing = ids.filter(id => !messageExists(id))
if (missing.length) throw new Error(`Unknown message ids: ${missing}`) Try / catch
try {
await deleteConversationMessages(ids)
} catch (e) {
if (/Unable to find ConversationMessage/.test(e.message)) await refreshMessages()
} Prevention
- Purge cached ids after deletion
- Refresh lists before batch operations
- Handle RecordNotFound as idempotent success where safe
When it happens
Trigger: Passing an id of a nonexistent, soft-deleted, or wrong-shard ConversationMessage in input[:ids]; ActiveRecord::RecordNotFound from find is translated to this message.
Common situations: Clients caching message ids after the message was deleted elsewhere; legacy numeric ids not converted to relay global ids; cross-shard lookups resolving 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/6efcc1951a9a1b61.
Report an issue: GitHub.
Appendix: source
Thrown at app/graphql/mutations/delete_conversation_messages.rb:49
raise GraphQL::ExecutionError, "Insufficient permissions"
end
messages = ConversationMessage.preload(:conversation).find(input[:ids])
if messages.map(&:conversation).uniq.length > 1
raise GraphQL::ExecutionError, "All ConversationMessages must exist within the same Conversation"
end
participant_record = current_user.all_conversations.find_by(conversation_id: messages.first.conversation.id)
raise GraphQL::ExecutionError, "Insufficient permissions" if participant_record.nil?
participant_record.remove_messages(*messages)
context[:deleted_models] = { conversation_messages: {} }
messages.each { |message| context[:deleted_models][:conversation_messages][message.id.to_s] = message }
{ conversation_message_ids: input[:ids] }
rescue ActiveRecord::RecordInvalid => e
errors_for(e.record)
rescue ActiveRecord::RecordNotFound
raise GraphQL::ExecutionError, "Unable to find ConversationMessage"
end
def self.conversation_message_ids_log_entry(entry, context)
context[:deleted_models][:conversation_messages][entry]
end
end
View on GitHub (pinned to 1c9f0bb801)