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

  1. Verify the message ids exist (ConversationMessage.exists?) before calling the mutation
  2. Refresh stale client state after deletes instead of reusing cached ids
  3. Ensure ids are passed as valid relay/legacy ids per the argument's prepare function
  4. 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

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)