Mintplex-Labs/anything-llm · error
No user prompt found. Must be last element in message array…
Error message
No user prompt found. Must be last element in message array with 'user' role.
What it means
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.
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: ...}.
Example fix
// before
messages: [
{ role: "system", content: "You are helpful." }
]
// after
messages: [
{ role: "system", content: "You are helpful." },
{ role: "user", content: "Hello" }
] Defensive patterns
Strategy: validation
Validate before calling
function lastMessageIsUser(messages) {
return Array.isArray(messages) && messages.length > 0 &&
messages[messages.length - 1]?.role === 'user';
}
if (!lastMessageIsUser(messages)) {
throw new Error('messages must end with a user-role message');
} Type guard
function isUserMessage(m) {
return !!m && typeof m === 'object' && m.role === 'user' && typeof m.content === 'string';
} Try / catch
try {
const res = await openai.chat.completions.create({ model: workspaceSlug, messages });
} catch (e) {
if (e.status === 400 && /No user prompt found/.test(e.response?.data?.error ?? '')) {
// reorder: ensure the last message has role 'user'
} else { throw e; }
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- e.message
- Invalid path name
- No docPath provided in request
- Tools must be an array
- addToWorkspaces must be a string of comma-separated…
AI-assisted analysis of Mintplex-Labs/anything-llm@f92433b4ea (2026-09-22).
Data as JSON: /api/errors/feac32b4a20ebabf.
Report an issue: GitHub.
Appendix: source
Thrown at server/endpoints/api/openai/index.js:120
#swagger.responses[403] = {
schema: {
"$ref": "#/definitions/InvalidAPIKey"
}
}
*/
try {
const {
model,
messages = [],
temperature,
stream = false,
} = reqBody(request);
const workspace = await Workspace.get({ slug: String(model) });
if (!workspace) return response.status(401).end();
const userMessage = messages.pop();
if (userMessage?.role !== "user") {
return response.status(400).json({
id: uuidv4(),
type: "abort",
textResponse: null,
sources: [],
close: true,
error:
"No user prompt found. Must be last element in message array with 'user' role.",
});
}
const systemPrompt =
extractTextContent(
messages.find((chat) => chat.role === "system")?.content
) ?? null;
const history = messages.filter((chat) => chat.role !== "system") ?? [];
if (!stream) {
const chatResult = await OpenAICompatibleChat.chatSync({View on GitHub (pinned to f92433b4ea)