{"record":{"id":"33ea6fbd402882e9","repo":"instructure/canvas-lms","slug":"not-found-create-conversation","errorCode":null,"errorMessage":"not found","messagePattern":"not found","errorType":"exception","errorClass":"GraphQL::ExecutionError","httpStatus":null,"severity":"error","filePath":"app/graphql/mutations/create_conversation.rb","lineNumber":148,"sourceCode":"        InstStatsd::Statsd.distributed_increment(\"inbox.conversation.sent.react\")\n        InstStatsd::Statsd.count(\"inbox.message.sent.recipients.react\", recipients.count)\n        if message.has_media_objects || input[:media_comment_id]\n          InstStatsd::Statsd.distributed_increment(\"inbox.message.sent.media.react\")\n        end\n        if message[:attachment_ids].present?\n          InstStatsd::Statsd.distributed_increment(\"inbox.message.sent.attachment.react\")\n        end\n        if context_type == \"Account\" || context_type.nil?\n          InstStatsd::Statsd.distributed_increment(\"inbox.conversation.sent.account_context.react\")\n        end\n        if input[:bulk_message]\n          InstStatsd::Statsd.distributed_increment(\"inbox.conversation.sent.individual_message_option.react\")\n        end\n        return { conversations: [conversation] }\n      end\n    end\n  rescue ActiveRecord::RecordNotFound\n    raise GraphQL::ExecutionError, \"not found\"\n  rescue ActiveRecord::RecordInvalid => e\n    errors_for(e.record)\n  rescue ConversationsHelper::InvalidContextError\n    validation_error(\n      I18n.t(\n        \"No context found for the following context code: %{context_code}\",\n        { context_code: input[:context_code] }\n      ),\n      attribute: \"context_code\"\n    )\n  rescue ConversationsHelper::InvalidContextPermissionsError\n    validation_error(\n      I18n.t(\n        \"Unable to send messages to users in %{context_name}\",\n        { context_name: context.name }\n      ),\n      attribute: \"permissions\"\n    )","sourceCodeStart":130,"sourceCodeEnd":166,"githubUrl":"https://github.com/instructure/canvas-lms/blob/1c9f0bb8013ed69c4f2efe11fd483025469b7e6c/app/graphql/mutations/create_conversation.rb#L130-L166","documentation":"create_conversation#resolve rescues ActiveRecord::RecordNotFound and raises GraphQL::ExecutionError 'not found'. Any record needed to build the conversation (recipient User, course/group context, participant) missing from the DB makes the whole mutation fail with this opaque message.","triggerScenarios":"Calling createConversation with recipient ids, context codes, or attachment/media ids that don't resolve: invalid recipient user ids, deleted context course, missing conversation participants, or bad enrollement-linked records.","commonSituations":"Recipient user deleted or on another shard; context_code references a deleted course/group; bulk recipients list contains one stale id so the entire send fails; API clients caching old user ids.","solutions":["Validate every recipient id resolves to an active User before calling","Confirm the context_code (course_/group_) references an existing, active context","Remove stale recipients and retry; find the failing id by querying each in console","Check shard routing so cross-shard user ids load in the current context"],"exampleFix":"// before\ncreateConversation(input: { recipients: [\"4\", \"999\"] }) // user 999 deleted\n// after\nvalid_ids = User.active.where(id: [4, 999]).pluck(:id)\ncreateConversation(input: { recipients: valid_ids.map(&:to_s), body: \"hi\" })","handlingStrategy":"validation","validationCode":"const users = await Promise.all(recipientIds.map(id => canvas.get(`/api/v1/users/${id}`).catch(() => null)))\nif (users.some(u => !u)) throw new Error('one or more recipients not found')","typeGuard":"function allRecipientsValid(users) { return Array.isArray(users) && users.length > 0 && users.every(u => u != null && u.id != null && u.workflow_state !== 'deleted') }","tryCatchPattern":"try {\n  await client.mutate({ mutation: CREATE_CONVERSATION, variables: { recipients, body } })\n} catch (e) {\n  if (e.message === 'not found') {\n    // bisect recipients to find the stale id, then resend without it\n  }\n  throw e\n}","preventionTips":["Validate each recipient id against the users API before sending","Resolve context codes to live course/group records first","Purge cached recipient lists when users are deleted or merged","Ensure cross-shard user ids are handled by the session's shard context"],"tags":["graphql","mutation","conversations","record-not-found"],"backgroundTag":"record-not-found","analyzedSha":"1c9f0bb8013ed69c4f2efe11fd483025469b7e6c","analyzedAt":"2026-09-15T20:33:18.891Z","contentChangedAt":"2026-09-15T20:33:18.891Z","schemaVersion":2},"datasetVersion":"2026-09-23T02:17:17.105Z"}