Mintplex-Labs/anything-llm · warning

Thread not found

Error message

Thread not found

What it means

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.

Source

Thrown at server/endpoints/api/workspaceThread/index.js:180

          "$ref": "#/definitions/InvalidAPIKey"
        }
      }
      */
      try {
        const { slug, threadSlug } = request.params;
        const { name } = reqBody(request);
        const workspace = await Workspace.get({ slug: String(slug) });
        if (!workspace) {
          response.status(404).json({ message: "Workspace not found" });
          return;
        }

        const thread = await WorkspaceThread.get({
          slug: String(threadSlug),
          workspace_id: workspace.id,
        });
        if (!thread) {
          response.status(404).json({ message: "Thread not found" });
          return;
        }

        const { thread: updatedThread, message } = await WorkspaceThread.update(
          thread,
          { name }
        );
        response.status(200).json({ thread: updatedThread, message });
      } catch (e) {
        console.error(e.message, e);
        response.sendStatus(500).end();
      }
    }
  );

  app.delete(
    "/v1/workspace/:slug/thread/:threadSlug",
    [validApiKey],

View on GitHub (pinned to 3aec848f28)

Solutions

  1. List the workspace's chats/threads (GET /api/v1/workspace/:slug/threads or thread chats endpoint) to get the current threadSlug
  2. Confirm the thread belongs to the exact workspace slug in the URL
  3. If the thread was deleted, create a new one via POST /api/v1/workspace/:slug/thread/new and use the returned slug
  4. Never guess thread slugs - always persist the slug returned by the create API

Example fix

// before
await updateThread(slug, 'My Thread', { name }); // passing thread NAME
// after
const thread = await findThreadByName(slug, 'My Thread'); // list threads, match on name
await updateThread(slug, thread.slug, { name });
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) throw new Error(`thread ${threadSlug} missing under ${slug}`);

Type guard

const isThreadRef = (r) => typeof r?.slug === 'string' && typeof r?.workspace_id === 'number' || typeof r?.workspace_id === 'string';

Prevention

When it happens

Trigger: 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.

Common situations: 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.

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


AI-assisted analysis of Mintplex-Labs/anything-llm@3aec848f28 (2026-08-18). Data as JSON: /api/errors/f191cb2b9300c710. Report an issue: GitHub.