Mintplex-Labs/anything-llm · error

Failed to revoke API key

Error message

Failed to revoke API key

What it means

Catch-all 500 for DELETE /browser-extension/api-keys/:id. It fires when BrowserExtensionApiKey.delete(id) reports failure (success:false, error re-thrown). Notably the raw string id is passed to delete() unparsed, so a non-numeric :id reaches the SQL layer and can fail binding in better-sqlite3 - unlike the 403 branch, which does parseInt. Otherwise it is a DB-level delete failure (locked DB, missing row constraint).

Source

Thrown at server/endpoints/browserExtension.js:218

        const { id } = request.params;
        const user = await userFromSession(request, response);

        if (multiUserMode(response) && user.role !== ROLES.admin) {
          const apiKey = await BrowserExtensionApiKey.get({
            id: parseInt(id),
            user_id: user?.id,
          });
          if (!apiKey) {
            return response.status(403).json({ error: "Unauthorized" });
          }
        }

        const { success, error } = await BrowserExtensionApiKey.delete(id);
        if (!success) throw new Error(error);
        response.status(200).json({ success: true });
      } catch (error) {
        console.error(error);
        response.status(500).json({ error: "Failed to revoke API key" });
      }
    }
  );
}

module.exports = { browserExtensionEndpoints };

View on GitHub (pinned to 3aec848f28)

Solutions

  1. Read server logs - the re-thrown error is the delete() failure reason.
  2. Use the numeric id returned by GET /browser-extension/api-keys in the URL.
  3. Retry once after a few seconds if the log shows 'database is locked'.
Defensive patterns

Strategy: validation

Validate before calling

if (!/^\d+$/.test(String(id))) throw new Error(`Invalid key id: ${id} - use the numeric id from the list endpoint`);

Type guard

const isNumericId = (v: unknown): v is string => typeof v === 'string' && /^\d+$/.test(v);

Try / catch

try { await revokeKey(id); }
catch (e) {
  if (e.status === 500 && /locked/i.test(String(e.body?.error))) { await sleep(1000); return revokeKey(id); }
  throw e;
}

Prevention

When it happens

Trigger: DELETE /browser-extension/api-keys/abc - the string 'abc' is bound where an integer id is expected; SQLITE_BUSY while another write holds the DB; schema drift after a partial migration.

Common situations: Hand-crafted URLs or scripts using the key string instead of id; two tabs revoking the same key at once.

Related errors


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