{"record":{"id":"94a24424d3f9d0b3","repo":"Mintplex-Labs/anything-llm","slug":"workspace-slug-not-found","errorCode":null,"errorMessage":"Workspace ${slug} not found.","messagePattern":"Workspace (.+?) not found\\.","errorType":"http","errorClass":null,"httpStatus":404,"severity":"warning","filePath":"server/endpoints/api/workspaceThread/index.js","lineNumber":403,"sourceCode":"      }\n      #swagger.responses[403] = {\n        schema: {\n          \"$ref\": \"#/definitions/InvalidAPIKey\"\n        }\n      }\n      */\n      try {\n        const { slug, threadSlug } = request.params;\n        const {\n          message,\n          mode = null,\n          userId,\n          attachments = [],\n          reset = false,\n        } = reqBody(request);\n        const workspace = await Workspace.get({ slug: String(slug) });\n        if (!workspace) {\n          response.status(404).json({\n            id: uuidv4(),\n            type: \"abort\",\n            textResponse: null,\n            sources: [],\n            close: true,\n            error: `Workspace ${slug} not found.`,\n          });\n          return;\n        }\n\n        const thread = await WorkspaceThread.get({\n          slug: String(threadSlug),\n          workspace_id: workspace.id,\n        });\n        if (!thread) {\n          response.status(404).json({\n            id: uuidv4(),\n            type: \"abort\",","sourceCodeStart":385,"sourceCodeEnd":421,"githubUrl":"https://github.com/Mintplex-Labs/anything-llm/blob/3aec848f2885144aa8f1e53b9731a04310d5d558/server/endpoints/api/workspaceThread/index.js#L385-L421","documentation":"HTTP 404 from POST /api/v1/workspace/:slug/thread/:threadSlug/chat when the workspace lookup returns null. The response uses the abort shape {type:'abort', close:true, error:'Workspace <slug> not found.'} so streaming-capable clients can handle it uniformly. Note this endpoint 404s for a bad workspace while the non-thread workspace chat returns 400 for the same condition.","triggerScenarios":"Chatting to a thread under a non-existent workspace slug; deleted workspace; workspace name or UUID used in place of slug.","commonSituations":"Client state holds slugs from before a workspace purge; scripts promoted between environments without updating slugs.","solutions":["Validate the workspace slug with GET /api/v1/workspace/:slug before chatting","Pull slugs from GET /api/v1/workspaces rather than hardcoding","Handle the 404 abort body and prompt re-selection of the workspace","Re-create the workspace or repoint to an existing one"],"exampleFix":"// before\nawait threadChat(slugFromEnv, threadSlug, message);\n// after\nif (!(await workspaceExists(slugFromEnv))) throw new Error(`workspace ${slugFromEnv} missing`);\nawait threadChat(slugFromEnv, threadSlug, message);","handlingStrategy":"validation","validationCode":"if (!(await fetch(`${BASE}/api/v1/workspace/${slug}`, { headers: AUTH }).then(r => r.ok)))\n  throw new Error(`workspace ${slug} not found - re-list workspaces`);","typeGuard":"function isAbortPayload(d) { return d?.type === 'abort' && typeof d.error === 'string'; }","tryCatchPattern":"try { const d = await threadChat(...); if (isAbortPayload(d)) throw new Error(d.error); }\ncatch (e) { if (/not found/.test(e.message)) await refreshWorkspaceCache(); throw e; }","preventionTips":["Check workspace existence before thread chat","Distinguish workspace-404 vs thread-404 by the error text to route recovery","Keep workspace references fresh via periodic listing"],"tags":["anythingllm","developer-api","workspace-thread","chat","http-404","not-found"],"backgroundTag":"resource-not-found","analyzedSha":"3aec848f2885144aa8f1e53b9731a04310d5d558","analyzedAt":"2026-08-18T10:02:21.017Z","schemaVersion":2},"datasetVersion":"2026-08-21T13:17:26.733Z"}