{"record":{"id":"f191cb2b9300c710","repo":"Mintplex-Labs/anything-llm","slug":"thread-not-found","errorCode":null,"errorMessage":"Thread not found","messagePattern":"Thread not found","errorType":"http","errorClass":null,"httpStatus":404,"severity":"warning","filePath":"server/endpoints/api/workspaceThread/index.js","lineNumber":180,"sourceCode":"          \"$ref\": \"#/definitions/InvalidAPIKey\"\n        }\n      }\n      */\n      try {\n        const { slug, threadSlug } = request.params;\n        const { name } = reqBody(request);\n        const workspace = await Workspace.get({ slug: String(slug) });\n        if (!workspace) {\n          response.status(404).json({ message: \"Workspace not found\" });\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({ message: \"Thread not found\" });\n          return;\n        }\n\n        const { thread: updatedThread, message } = await WorkspaceThread.update(\n          thread,\n          { name }\n        );\n        response.status(200).json({ thread: updatedThread, message });\n      } catch (e) {\n        console.error(e.message, e);\n        response.sendStatus(500).end();\n      }\n    }\n  );\n\n  app.delete(\n    \"/v1/workspace/:slug/thread/:threadSlug\",\n    [validApiKey],","sourceCodeStart":162,"sourceCodeEnd":198,"githubUrl":"https://github.com/Mintplex-Labs/anything-llm/blob/3aec848f2885144aa8f1e53b9731a04310d5d558/server/endpoints/api/workspaceThread/index.js#L162-L198","documentation":"HTTP 404 from POST /api/v1/workspace/:slug/thread/:threadSlug/update when no thread matches BOTH slug=threadSlug AND workspace_id=workspace.id. Thread lookup is scoped to the parent workspace, so a thread slug that exists under a different workspace still 404s. The thread slug is the thread's URL identifier, not its name.","triggerScenarios":"Right thread slug under the wrong workspace; thread was deleted from the UI; using the thread's display name or numeric id instead of its slug; stale threadSlug cached by the client after threads were recreated.","commonSituations":"Duplicating a workspace and reusing thread slugs from the original; client-side autocomplete storing old thread slugs; assuming thread slugs are globally unique when they are only unique per workspace.","solutions":["List the workspace's chats/threads (GET /api/v1/workspace/:slug/threads or thread chats endpoint) to get the current threadSlug","Confirm the thread belongs to the exact workspace slug in the URL","If the thread was deleted, create a new one via POST /api/v1/workspace/:slug/thread/new and use the returned slug","Never guess thread slugs - always persist the slug returned by the create API"],"exampleFix":"// before\nawait updateThread(slug, 'My Thread', { name }); // passing thread NAME\n// after\nconst thread = await findThreadByName(slug, 'My Thread'); // list threads, match on name\nawait updateThread(slug, thread.slug, { name });","handlingStrategy":"validation","validationCode":"const ok = await fetch(`${BASE}/api/v1/workspace/${slug}/thread/${threadSlug}/chats`, { headers: AUTH }).then(r => r.ok);\nif (!ok) throw new Error(`thread ${threadSlug} missing under ${slug}`);","typeGuard":"const isThreadRef = (r) => typeof r?.slug === 'string' && typeof r?.workspace_id === 'number' || typeof r?.workspace_id === 'string';","tryCatchPattern":null,"preventionTips":["Persist the thread slug returned by thread/new - never construct it","Remember thread slugs are scoped per workspace","On 404, re-list threads and rebuild the reference"],"tags":["anythingllm","developer-api","workspace-thread","http-404","not-found","scoping"],"backgroundTag":"resource-not-found","analyzedSha":"3aec848f2885144aa8f1e53b9731a04310d5d558","analyzedAt":"2026-08-18T10:02:21.017Z","schemaVersion":2},"datasetVersion":"2026-08-21T13:17:26.733Z"}