Mintplex-Labs/anything-llm · error

Invalid session ID.

Error message

Invalid session ID.

What it means

Session validation inside canRespond: the body's sessionId must be a string and pass uuid validate(); otherwise HTTP 404 with an abort payload 'Invalid session ID.'. The 404 status (not 400) reflects that the session does not exist. Widgets are expected to generate one UUID per conversation and keep sending it for follow-ups.

Source

Thrown at server/utils/middleware/embedMiddleware.js:100

      });
      return;
    }

    if (allowedHosts !== null && !allowedHosts.includes(host)) {
      response.status(401).json({
        id: uuidv4(),
        type: "abort",
        textResponse: null,
        sources: [],
        close: true,
        error: "Invalid request.",
      });
      return;
    }

    const { sessionId, message } = reqBody(request);
    if (typeof sessionId !== "string" || !validate(String(sessionId))) {
      response.status(404).json({
        id: uuidv4(),
        type: "abort",
        textResponse: null,
        sources: [],
        close: true,
        error: "Invalid session ID.",
      });
      return;
    }

    if (!message?.length || !VALID_CHAT_MODE.includes(embed.chat_mode)) {
      response.status(400).json({
        id: uuidv4(),
        type: "abort",
        textResponse: null,
        sources: [],
        close: true,
        error: !message?.length

View on GitHub (pinned to 3aec848f28)

Solutions

  1. Generate the session id once per conversation with crypto.randomUUID() and reuse it for all messages in that conversation
  2. Ensure the body field is exactly sessionId and is a string UUID
  3. If integrating server-side, keep the uuid with the user's conversation state (e.g. localStorage/session storage in a widget)

Example fix

// before
body: JSON.stringify({ sessionId: 'session-1', message: text }) // -> 404 Invalid session ID.

// after
const sessionId = crypto.randomUUID(); // once per conversation, then reuse
body: JSON.stringify({ sessionId, message: text })
Defensive patterns

Strategy: type-guard

Validate before calling

const { validate } = require('uuid');
const sessionId = store.get('embedSessionId') ?? crypto.randomUUID();
store.set('embedSessionId', sessionId);
if (!validate(sessionId)) throw new Error('sessionId must be a UUID');

Type guard

const isValidSessionId = (id) =>
  typeof id === 'string' && /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(id);
// or: const { validate } = require('uuid'); const isValidSessionId = (id) => typeof id === 'string' && validate(id);

Try / catch

if (res.status === 404) {
  const data = await res.json();
  if (/Invalid session ID/.test(data.error ?? '')) resetSessionId(); // regenerate and retry once
}

Prevention

When it happens

Trigger: POSTing a chat message with sessionId missing, null, a number, or any non-UUID string ('session-1', 'abc', a nanoid); sending an unquoted UUID in form-encoded bodies; forgetting to persist the generated id between messages so every send uses a fresh invalid value.

Common situations: Custom widget integrations that use their own incremental ids; JSON serialization dropping the field; SSR frameworks rendering the widget before the id is created.

Related errors


AI-assisted analysis of Mintplex-Labs/anything-llm@3aec848f28 (2026-08-18). Data as JSON: /api/errors/10e420ae429e8b65. Report an issue: GitHub.