chatboxai/chatbox · error · Error

No user message found

Error message

No user message found

What it means

Thrown by orchestratePictureGeneration in a picture-type session when findLast over messages before the target index yields no user-role message. The picture flow uses the most recent user message as the image prompt; without one generation has no prompt source. The code comment marks this as 'Should not happen', so it indicates session-state corruption rather than normal use.

Source

Thrown at src/renderer/stores/session/pictures.ts:79

      if (targetMsgIx > 0) {
        break
      }
    }
    if (targetMsgIx <= 0) {
      return
    }
  }

  try {
    const model = await createModel(settings)

    // Picture message generation
    if (session.type === 'picture') {
      // Take the most recent user message before the current message as prompt
      const userMessage = messages.slice(0, targetMsgIx).findLast((m) => m.role === 'user')
      if (!userMessage) {
        // Should not happen - user message not found
        throw new Error('No user message found')
      }

      const insertImage = async (image: MessageImagePart) => {
        targetMsg.contentParts.push(image)
        targetMsg.status = []
        await modifyMessage(sessionId, targetMsg, true)
      }
      let imageIndex = 0
      await generateImage(
        model,
        {
          message: userMessage,
          num: settings.imageGenerateNum || 1,
        },
        async (picBase64) => {
          const storageKey = StorageKeyGenerator.picture(`${session.id}:${targetMsg.id}:${imageIndex++}`)
          // Image needs to be stored in indexedDB, if using OpenAI's image link directly, the link will expire over time
          await storage.setBlob(storageKey, picBase64)

View on GitHub (pinned to 81571269ad)

Solutions

  1. Guard the regenerate UI: disable it when no preceding user message exists for the target.
  2. Return early (no-op) instead of throwing for this invariant violation, since the comment says it should not happen.
  3. Run a session-repair pass that prunes orphaned assistant messages.
  4. Log the message ids/roles to Sentry so the corruption source can be traced.

Example fix

// before
const userMessage = messages.slice(0, targetMsgIx).findLast((m) => m.role === 'user')
if (!userMessage) {
  throw new Error('No user message found')
}
// after
const userMessage = messages.slice(0, targetMsgIx).findLast((m) => m.role === 'user')
if (!userMessage) {
  log.error('orchestratePictureGeneration: no preceding user message', { sessionId, targetMsgIx, roles: messages.map((m) => m.role) })
  return
}
Defensive patterns

Strategy: validation

Validate before calling

const userMessage = messages.slice(0, targetMsgIx).findLast((m) => m.role === 'user')
if (!userMessage) {
  log.error('orchestratePictureGeneration: no preceding user message', { sessionId })
  return
}

Type guard

function hasPrecedingUserMessage(msgs: { role: string }[], upTo: number): boolean {
  return msgs.slice(0, upTo).some((m) => m.role === 'user')
}

Prevention

When it happens

Trigger: A picture session's message list has no user message preceding the target assistant message: an orphaned assistant message, a regenerate triggered on a thread where the user message was deleted, or corrupted/edited session storage. Also possible if targetMsgIx resolved to 0 via a thread but no user message precedes it.

Common situations: User deleted their prompt message then hit regenerate, a sync/import produced an assistant message with no parent user message, or message-edit removed the user role.

Related errors


AI-assisted analysis of chatboxai/chatbox@81571269ad (2026-08-12). Data as JSON: /api/errors/c79e4d18e310bdbf. Report an issue: GitHub.