Mintplex-Labs/anything-llm · warning
Message is empty.
Error message
Message is empty.
What it means
Deliberate 400 from POST /workspace/:slug/stream-chat when `message` is not a string or is empty/whitespace-only. The check runs before the SSE stream opens, and the 400 body is shaped like an abort event (id/type/close) so streaming clients terminate cleanly. Identical validation exists on the thread variant of the route.
Source
Thrown at server/endpoints/chat.js:33
const { writeResponseChunk } = require("../utils/helpers/chat/responses");
const { WorkspaceThread } = require("../models/workspaceThread");
const { User } = require("../models/user");
const { getModelTag } = require("./utils");
function chatEndpoints(app) {
if (!app) return;
app.post(
"/workspace/:slug/stream-chat",
[validatedRequest, flexUserRoleValid([ROLES.all]), validWorkspaceSlug],
async (request, response) => {
try {
const user = await userFromSession(request, response);
const { message, attachments = [] } = reqBody(request);
const workspace = response.locals.workspace;
if (typeof message !== "string" || message.trim().length === 0) {
response.status(400).json({
id: uuidv4(),
type: "abort",
textResponse: null,
sources: [],
close: true,
error: "Message is empty.",
});
return;
}
response.setHeader("Cache-Control", "no-cache");
response.setHeader("Content-Type", "text/event-stream");
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Connection", "keep-alive");
response.flushHeaders();
if (multiUserMode(response) && !(await User.canSendChat(user))) {
writeResponseChunk(response, {View on GitHub (pinned to 3aec848f28)
Solutions
- Send `message` as a non-empty, trimmed string in the JSON body.
- If you intended an attachments-only turn, note the API still requires a non-empty message - add accompanying text.
- Guard client-side before POSTing (see exampleFix).
Example fix
// before
fetch(`/workspace/${slug}/stream-chat`, { method: "POST", body: JSON.stringify({ message: input.value, attachments }) });
// after
const message = input.value.trim();
if (!message) return showError("Type a message first");
fetch(`/workspace/${slug}/stream-chat`, { method: "POST", body: JSON.stringify({ message, attachments }) }); Defensive patterns
Strategy: validation
Validate before calling
const message = typeof rawMessage === 'string' ? rawMessage.trim() : '';
if (!message) throw new Error('Refusing to send: message is empty');
await streamChat(slug, { message, attachments }); Type guard
const isNonEmptyMessage = (m: unknown): m is string => typeof m === 'string' && m.trim().length > 0;
Prevention
- Disable the send button until the composer has non-whitespace text.
- Trim input client-side so server-side trimming can never surprise you.
- Remember attachments do not replace the required message field.
When it happens
Trigger: message missing from the JSON body; message sent as a number, object, or null (fails typeof check); message is "" or " "; attachments-only POST with no message field.
Common situations: Frontend firing the request before input state populates; automated/API clients omitting message; whitespace-only input that only gets trimmed server-side.
Related errors
- Message is empty
- GroqAI:streamChatCompletion: ${this.model} is not valid for
- Name and config are required
- Query parameter cannot be empty.
- ${resolvedMode} is not a valid mode.
AI-assisted analysis of Mintplex-Labs/anything-llm@3aec848f28 (2026-08-18).
Data as JSON: /api/errors/adc5a4106e82d437.
Report an issue: GitHub.