Mintplex-Labs/anything-llm · error

Failed to disconnect and revoke API key

Error message

Failed to disconnect and revoke API key

What it means

HTTP 500 from DELETE /api/browser-extension/disconnect, which revokes the browser extension's API key via BrowserExtensionApiKey.delete(apiKeyId). The handler throws (and converts to this message) when delete reports {success:false, error}, or when the DB delete itself throws - e.g. the key row was already removed, the database is unavailable, or response.locals.apiKey was not populated. The original error is only in the server console.

Source

Thrown at server/endpoints/browserExtension.js:57

          .json({ connected: false, error: "Failed to fetch workspaces" });
      }
    }
  );

  app.delete(
    "/browser-extension/disconnect",
    [validBrowserExtensionApiKey],
    async (_request, response) => {
      try {
        const apiKeyId = response.locals.apiKey.id;
        const { success, error } =
          await BrowserExtensionApiKey.delete(apiKeyId);
        if (!success) throw new Error(error);
        response.status(200).json({ success: true });
      } catch (error) {
        console.error(error);
        response
          .status(500)
          .json({ error: "Failed to disconnect and revoke API key" });
      }
    }
  );

  app.get(
    "/browser-extension/workspaces",
    [validBrowserExtensionApiKey],
    async (request, response) => {
      try {
        const user = await userFromSession(request, response);
        const workspaces = multiUserMode(response)
          ? await Workspace.whereWithUser(user)
          : await Workspace.where();

        response.status(200).json({ workspaces });
      } catch (error) {
        console.error(error);

View on GitHub (pinned to 3aec848f28)

Solutions

  1. Check server logs for the console.error output naming the real cause
  2. Retry disconnect once after refreshing the extension - an already-revoked key usually resolves itself
  3. If it persists, verify DB health (volume, disk, locks)
  4. Re-connect the extension to mint a new key, which replaces dangling state

Example fix

// before
await disconnect(); // fire-and-forget, throws on 500
// after
const res = await disconnect();
if (!res.ok && res.status !== 500) await reconnect();
// 500 with revoked/missing key is effectively disconnected - drop local key either way
clearStoredKey();
Defensive patterns

Strategy: fallback

Type guard

function isDisconnectFailure(d) { return typeof d?.error === 'string' && /disconnect/i.test(d.error); }

Try / catch

try { await disconnect(); }
catch (e) {
  clearLocalApiKey(); // 500 here often means the key is already gone - clearing local state is the safe end state
  if (persistsOnNextConnect()) await reconnect();
}

Prevention

When it happens

Trigger: Disconnect clicked twice (second call may already lack a valid key row); database down or locked when deleting the key; middleware and handler disagreeing on the current key after rotation.

Common situations: Retry storms from the extension UI racing multiple disconnects; server storage issues; a key revoked out-of-band (expired/cleanup job) before the user pressed disconnect.

Related errors


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