{"record":{"id":"feac32b4a20ebabf","repo":"Mintplex-Labs/anything-llm","slug":"no-user-prompt-found-must-be-last-element-in-message-array","errorCode":null,"errorMessage":"No user prompt found. Must be last element in message array with 'user' role.","messagePattern":"No user prompt found\\. Must be last element in message array with 'user' role\\.","errorType":"http","errorClass":null,"httpStatus":400,"severity":"error","filePath":"server/endpoints/api/openai/index.js","lineNumber":120,"sourceCode":"      #swagger.responses[403] = {\n        schema: {\n          \"$ref\": \"#/definitions/InvalidAPIKey\"\n        }\n      }\n      */\n      try {\n        const {\n          model,\n          messages = [],\n          temperature,\n          stream = false,\n        } = reqBody(request);\n        const workspace = await Workspace.get({ slug: String(model) });\n        if (!workspace) return response.status(401).end();\n\n        const userMessage = messages.pop();\n        if (userMessage?.role !== \"user\") {\n          return response.status(400).json({\n            id: uuidv4(),\n            type: \"abort\",\n            textResponse: null,\n            sources: [],\n            close: true,\n            error:\n              \"No user prompt found. Must be last element in message array with 'user' role.\",\n          });\n        }\n\n        const systemPrompt =\n          extractTextContent(\n            messages.find((chat) => chat.role === \"system\")?.content\n          ) ?? null;\n        const history = messages.filter((chat) => chat.role !== \"system\") ?? [];\n\n        if (!stream) {\n          const chatResult = await OpenAICompatibleChat.chatSync({","sourceCodeStart":102,"sourceCodeEnd":138,"githubUrl":"https://github.com/Mintplex-Labs/anything-llm/blob/f92433b4ea0598492a1e6645ea22addbb4dd1287/server/endpoints/api/openai/index.js#L102-L138","documentation":"The OpenAI-compatible chat endpoint pops the last message from the messages array and requires it to have role 'user', since the workspace chat is driven by the user's prompt. If the array is empty or the last message is not a user message, it returns a 400 abort payload with this error text.","triggerScenarios":"POSTing to /v1/chat/completions (OpenAI-compatible) with messages=[] or with the last message having role 'system'/'assistant', which many multi-turn clients do when appending context after the user turn.","commonSituations":"Clients that append a trailing system message (e.g. some agent frameworks ordering messages as [user, system]); empty messages arrays on first call; OpenAI SDK misuse where the prompt was passed as a string instead of a messages array; ported code from the completion (prompt) API to the chat API.","solutions":["Ensure the messages array ends with a message whose role is 'user'.","Send at least one message; an empty array always triggers this error.","If your client appends system messages after the user turn, reorder so the user message is last.","Verify you are using the chat completions API shape ({messages:[...]}) and not {prompt: ...}."],"exampleFix":"// before\nmessages: [\n  { role: \"system\", content: \"You are helpful.\" }\n]\n// after\nmessages: [\n  { role: \"system\", content: \"You are helpful.\" },\n  { role: \"user\", content: \"Hello\" }\n]","handlingStrategy":"validation","validationCode":"function lastMessageIsUser(messages) {\n  return Array.isArray(messages) && messages.length > 0 &&\n    messages[messages.length - 1]?.role === 'user';\n}\nif (!lastMessageIsUser(messages)) {\n  throw new Error('messages must end with a user-role message');\n}","typeGuard":"function isUserMessage(m) {\n  return !!m && typeof m === 'object' && m.role === 'user' && typeof m.content === 'string';\n}","tryCatchPattern":"try {\n  const res = await openai.chat.completions.create({ model: workspaceSlug, messages });\n} catch (e) {\n  if (e.status === 400 && /No user prompt found/.test(e.response?.data?.error ?? '')) {\n    // reorder: ensure the last message has role 'user'\n  } else { throw e; }\n}","preventionTips":["Always end the messages array with the user's prompt.","Never append system/assistant messages after the user turn in this API.","Send a non-empty messages array on every call.","Use the chat completions payload shape, not the legacy prompt string."],"tags":["openai-compatible","validation","api","messages"],"backgroundTag":"invalid-argument-value","analyzedSha":"f92433b4ea0598492a1e6645ea22addbb4dd1287","analyzedAt":"2026-09-22T02:13:38.154Z","contentChangedAt":"2026-09-22T02:13:38.154Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}