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
- Guard the regenerate UI: disable it when no preceding user message exists for the target.
- Return early (no-op) instead of throwing for this invariant violation, since the comment says it should not happen.
- Run a session-repair pass that prunes orphaned assistant messages.
- 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
- Disable regenerate when no preceding user message exists.
- Run a session-repair pass that prunes orphaned assistant messages.
- Log message roles on the invariant violation to trace corruption.
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.