Mintplex-Labs/anything-llm · warning
Thread ${threadSlug} not found.
Error message
Thread ${threadSlug} not found. What it means
HTTP 404 from POST /api/v1/workspace/:slug/thread/:threadSlug/chat when WorkspaceThread.get({slug:threadSlug, workspace_id}) finds no thread. The thread must belong to the resolved workspace; a thread that exists elsewhere still fails. The abort-shaped body names the missing threadSlug specifically, distinguishing it from the workspace-level 404.
Source
Thrown at server/endpoints/api/workspaceThread/index.js:419
const workspace = await Workspace.get({ slug: String(slug) });
if (!workspace) {
response.status(404).json({
id: uuidv4(),
type: "abort",
textResponse: null,
sources: [],
close: true,
error: `Workspace ${slug} not found.`,
});
return;
}
const thread = await WorkspaceThread.get({
slug: String(threadSlug),
workspace_id: workspace.id,
});
if (!thread) {
response.status(404).json({
id: uuidv4(),
type: "abort",
textResponse: null,
sources: [],
close: true,
error: `Thread ${threadSlug} not found.`,
});
return;
}
const resolvedMode = mode ?? workspace.chatMode;
if (
(!message?.length || !VALID_CHAT_MODE.includes(resolvedMode)) &&
!reset
) {
response.status(400).json({
id: uuidv4(),
type: "abort",View on GitHub (pinned to 3aec848f28)
Solutions
- List threads for the workspace and use a current slug
- If missing, create the thread: POST /api/v1/workspace/:slug/thread/new, then chat using the returned slug
- On 404, invalidate the cached thread and re-resolve once
- Ensure the threadSlug comes from the API response field slug, not name
Example fix
// before
const res = await chat(slug, cachedThreadSlug, message);
// after
let threadSlug = cachedThreadSlug;
if (!(await threadExists(slug, threadSlug)))
threadSlug = (await createThread(slug, { name: 'recovered' })).slug;
const res = await chat(slug, threadSlug, message); Defensive patterns
Strategy: fallback
Validate before calling
if (!(await threadExists(slug, threadSlug)))
threadSlug = (await createThread(slug, { name: 'auto-recovered' })).slug; Type guard
function isThreadNotFound(d) { return d?.type === 'abort' && /Thread .* not found/.test(d.error ?? ''); } Try / catch
try { await threadChat(slug, threadSlug, msg); }
catch (e) { if (isThreadNotFound(e.payload)) { threadSlug = await createThread(slug); await threadChat(slug, threadSlug, msg); } else throw e; } Prevention
- Store the thread slug from the create response
- Revalidate thread before long-running sessions
- Auto-create the thread on 404 when idempotency is acceptable
When it happens
Trigger: Correct workspace, wrong or deleted thread slug; thread name used instead of slug; thread removed by another user/session between listing and chatting.
Common situations: Long-lived clients caching a threadSlug past deletion; concurrent users pruning threads; UI deep-links to removed threads.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
- Workspace ${slug} not found.
- Workspace not found
- Thread not found
- Message is empty
- ${resolvedMode} is not a valid mode.
AI-assisted analysis of Mintplex-Labs/anything-llm@3aec848f28 (2026-08-18).
Data as JSON: /api/errors/8c0290a7e7e1ed52.
Report an issue: GitHub.