Mintplex-Labs/anything-llm · error
Internal Server Error
Error message
Internal Server Error
What it means
Returned by POST /v1/workspace/:slug/thread/new when WorkspaceThread.new, Telemetry.sendTelemetry, or EventLogs.logEvent throws after the workspace is successfully found. The handler at server/endpoints/api/workspaceThread/index.js:104 catches errors from the thread creation pipeline. WorkspaceThread.new creates a Prisma record in the workspace_threads table — it can fail on DB constraints (duplicate slug if a custom thread slug collides with an existing one). As with error 585, if Telemetry.sendTelemetry throws after the thread is created, the thread exists in the DB but the client sees a 500 — a silent partial-success state.
Source
Thrown at server/endpoints/api/workspaceThread/index.js:106
workspace,
userId ? Number(userId) : null,
{ name, slug }
);
await Telemetry.sendTelemetry("workspace_thread_created", {
multiUserMode: multiUserMode(response),
LLMSelection: process.env.LLM_PROVIDER || "openai",
Embedder: process.env.EMBEDDING_ENGINE || "inherit",
VectorDbSelection: process.env.VECTOR_DB || "lancedb",
TTSSelection: process.env.TTS_PROVIDER || "native",
});
await EventLogs.logEvent("api_workspace_thread_created", {
workspaceName: workspace?.name || "Unknown Workspace",
});
response.status(200).json({ thread, message });
} catch (e) {
console.error(e.message, e);
response.sendStatus(500).end();
}
}
);
app.post(
"/v1/workspace/:slug/thread/:threadSlug/update",
[validApiKey],
async (request, response) => {
/*
#swagger.tags = ['Workspace Threads']
#swagger.description = 'Update thread name by its unique slug.'
#swagger.parameters['slug'] = {
in: 'path',
description: 'Unique slug of workspace',
required: true,
type: 'string'
}
#swagger.parameters['threadSlug'] = {View on GitHub (pinned to 526360e320)
Solutions
- Check server logs to determine whether WorkspaceThread.new, Telemetry.sendTelemetry, or EventLogs.logEvent threw.
- If providing a custom thread `slug` in the body, ensure it is unique within the workspace.
- If providing a `userId`, ensure it references a valid user (in multi-user mode): GET /v1/users to verify.
- After a 500, check if the thread was actually created via GET /v1/workspace/:slug — it may exist as a partial-success artifact.
- If telemetry is the culprit, disable telemetry events if your environment blocks outbound network calls.
- Omit the body `slug` to let WorkspaceThread.new auto-generate a unique slug.
Example fix
// before — custom slug that may collide
await fetch('/v1/workspace/my-ws/thread/new', {
method: 'POST',
body: JSON.stringify({ slug: 'my-thread', userId: 999 })
});
// after — let the system generate the slug, verify userId exists
await fetch('/v1/workspace/my-ws/thread/new', {
method: 'POST',
body: JSON.stringify({ name: 'My Thread' })
}); Defensive patterns
Strategy: validation
Validate before calling
// Validate thread creation body and verify workspace/user exist
async function validateThreadCreation(slug, body, apiKey) {
const wsRes = await fetch('/v1/workspaces', { headers: { Authorization: `Bearer ${apiKey}` } });
const { workspaces } = await wsRes.json();
if (!workspaces.some(w => w.slug === slug))
return { valid: false, error: 'Workspace not found' };
if (body.slug) {
// Custom slugs risk collision — warn the caller
console.warn('Custom thread slug provided — ensure it is unique within the workspace');
}
if (body.userId != null && typeof body.userId !== 'number')
return { valid: false, error: 'userId must be a number' };
return { valid: true };
} Try / catch
try {
const check = await validateThreadCreation(slug, body, API_KEY);
if (!check.valid) throw new Error(check.error);
const res = await fetch(`/v1/workspace/${slug}/thread/new`, {
method: 'POST',
headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${API_KEY}` },
body: JSON.stringify(body)
});
if (res.status === 500) {
// CRITICAL: thread may have been created before telemetry threw.
// Verify via workspace thread listing
throw new Error('Thread creation may have partially succeeded — verify via GET endpoint');
}
return await res.json();
} catch (e) { console.error(e); } Prevention
- After a 500 on thread creation, verify via GET /v1/workspace/:slug whether the thread was partially created.
- Disable telemetry in air-gapped/firewalled environments to prevent telemetry-throws from masking successful operations.
- Omit the body `slug` to let the system auto-generate a unique thread slug, avoiding collision errors.
- If providing userId, verify it references a valid user in multi-user mode.
- Do not confuse the workspace slug (URL param) with the thread slug (body param).
When it happens
Trigger: POST /v1/workspace/valid-slug/thread/new with a body `slug` value that already exists for a thread in the same workspace (unique constraint violation). Also when userId references a non-existent user (the code passes userId to WorkspaceThread.new which creates the thread with a foreign key to users — if the user does not exist, the FK constraint fires). When Telemetry.sendTelemetry throws due to network restrictions. When EventLogs.logEvent fails (DB issue). In single-user mode, passing a userId is nullified (line 85), but in multi-user mode an invalid userId is passed through.
Common situations: Air-gapped deployments where telemetry is blocked, causing the thread to be created but the response to be 500. Passing a custom thread slug that duplicates an existing thread slug in the same workspace. Passing a userId that was deleted or never existed (FK violation). Database connection issues during the Prisma create.
Understand the failure class
- HTTP status errors: handling 4xx and 5xx responses — how to handle 4xx and 5xx responses properly.
Related errors
AI-assisted analysis of Mintplex-Labs/anything-llm@526360e320 (2026-08-13).
Data as JSON: /api/errors/56774cb6902fb902.
Report an issue: GitHub.