Mintplex-Labs/anything-llm · warning
Workspace ${slug} or thread ${threadSlug} is not valid.
Error message
Workspace ${slug} or thread ${threadSlug} is not valid. What it means
HTTP 400 from POST /api/v1/workspace/:slug/thread/:threadSlug/stream-chat when either the workspace or thread lookup is null, with one message covering both cases. Subtlety: the code calls WorkspaceThread.get({workspace_id: workspace.id}) BEFORE the null check on workspace, so a completely missing workspace usually throws a TypeError ('Cannot read properties of null') that lands in the catch handler instead; this 400 therefore fires most often when the workspace resolves but the thread does not, or when Workspace.get returns undefined.
Source
Thrown at server/endpoints/api/workspaceThread/index.js:591
}
*/
try {
const { slug, threadSlug } = request.params;
const {
message,
mode = null,
userId,
attachments = [],
reset = false,
} = reqBody(request);
const workspace = await Workspace.get({ slug: String(slug) });
const thread = await WorkspaceThread.get({
slug: String(threadSlug),
workspace_id: workspace.id,
});
if (!workspace || !thread) {
response.status(400).json({
id: uuidv4(),
type: "abort",
textResponse: null,
sources: [],
close: true,
error: `Workspace ${slug} or thread ${threadSlug} is not valid.`,
});
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
- Check the thread exists under this workspace via the thread chats endpoint first
- If the error string appears with a valid workspace, focus on the threadSlug - it is the usual culprit
- If the server log shows a TypeError instead, your workspace slug itself is wrong - resolve it via GET /api/v1/workspaces
- Create the thread with POST /v1/workspace/:slug/thread/new when missing and use the returned slug
Example fix
// before
await streamThreadChat(slug, threadSlug, message);
// after
const ok = await fetch(`${BASE}/api/v1/workspace/${slug}/thread/${threadSlug}/chats`, { headers: AUTH }).then(r => r.ok);
if (!ok) threadSlug = (await createThread(slug)).slug; // then stream Defensive patterns
Strategy: validation
Validate before calling
const ok = await fetch(`${BASE}/api/v1/workspace/${slug}/thread/${threadSlug}/chats`, { headers: AUTH }).then(r => r.ok);
if (!ok) threadSlug = (await createThread(slug)).slug; Type guard
function isWorkspaceOrThreadInvalid(d) { return d?.type === 'abort' && /is not valid/.test(d.error ?? ''); } Try / catch
try { await streamThreadChat(slug, threadSlug, body); }
catch (e) { if (isWorkspaceOrThreadInvalid(e.payload)) { await revalidateSlugs(); } else throw e; } Prevention
- Pre-validate both slugs (workspace first - a missing workspace can surface as a TypeError 500 here, not this 400)
- Create missing threads before streaming
- Handle the abort chunk inside the SSE consumer
When it happens
Trigger: Valid workspace slug with a thread slug that is deleted or belongs to another workspace (400); completely unknown workspace slug often surfaces as the catch path with a TypeError message rather than this 400; sending thread name instead of thread slug.
Common situations: Stale thread references after thread deletion; duplicated workspaces reusing thread slugs; clients assuming thread slugs are global.
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 not found
- Thread not found
- Workspace ${slug} not found.
- Thread ${threadSlug} not found.
- Message is empty
AI-assisted analysis of Mintplex-Labs/anything-llm@3aec848f28 (2026-08-18).
Data as JSON: /api/errors/11aa4ab2be8e85ed.
Report an issue: GitHub.