{"record":{"id":"c79e4d18e310bdbf","repo":"chatboxai/chatbox","slug":"no-user-message-found","errorCode":null,"errorMessage":"No user message found","messagePattern":"No user message found","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/renderer/stores/session/pictures.ts","lineNumber":79,"sourceCode":"      if (targetMsgIx > 0) {\n        break\n      }\n    }\n    if (targetMsgIx <= 0) {\n      return\n    }\n  }\n\n  try {\n    const model = await createModel(settings)\n\n    // Picture message generation\n    if (session.type === 'picture') {\n      // Take the most recent user message before the current message as prompt\n      const userMessage = messages.slice(0, targetMsgIx).findLast((m) => m.role === 'user')\n      if (!userMessage) {\n        // Should not happen - user message not found\n        throw new Error('No user message found')\n      }\n\n      const insertImage = async (image: MessageImagePart) => {\n        targetMsg.contentParts.push(image)\n        targetMsg.status = []\n        await modifyMessage(sessionId, targetMsg, true)\n      }\n      let imageIndex = 0\n      await generateImage(\n        model,\n        {\n          message: userMessage,\n          num: settings.imageGenerateNum || 1,\n        },\n        async (picBase64) => {\n          const storageKey = StorageKeyGenerator.picture(`${session.id}:${targetMsg.id}:${imageIndex++}`)\n          // Image needs to be stored in indexedDB, if using OpenAI's image link directly, the link will expire over time\n          await storage.setBlob(storageKey, picBase64)","sourceCodeStart":61,"sourceCodeEnd":97,"githubUrl":"https://github.com/chatboxai/chatbox/blob/81571269addb6bafb589a920b2883f1e1e084fd1/src/renderer/stores/session/pictures.ts#L61-L97","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nconst userMessage = messages.slice(0, targetMsgIx).findLast((m) => m.role === 'user')\nif (!userMessage) {\n  throw new Error('No user message found')\n}\n// after\nconst userMessage = messages.slice(0, targetMsgIx).findLast((m) => m.role === 'user')\nif (!userMessage) {\n  log.error('orchestratePictureGeneration: no preceding user message', { sessionId, targetMsgIx, roles: messages.map((m) => m.role) })\n  return\n}","handlingStrategy":"validation","validationCode":"const userMessage = messages.slice(0, targetMsgIx).findLast((m) => m.role === 'user')\nif (!userMessage) {\n  log.error('orchestratePictureGeneration: no preceding user message', { sessionId })\n  return\n}","typeGuard":"function hasPrecedingUserMessage(msgs: { role: string }[], upTo: number): boolean {\n  return msgs.slice(0, upTo).some((m) => m.role === 'user')\n}","tryCatchPattern":null,"preventionTips":["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."],"tags":["picture-session","messages","state-invariant","regenerate"],"backgroundTag":null,"analyzedSha":"81571269addb6bafb589a920b2883f1e1e084fd1","analyzedAt":"2026-08-12T21:51:44.981Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}