mem0ai/mem0 · error · AuthError

Authentication failed. Your API key may be invalid or expire

Error message

Authentication failed. Your API key may be invalid or expired.

What it means

Thrown by the Mem0 REST server when an X-API-Key header was presented but no active, non-revoked API key row matches it. The server looks up candidates by key prefix, then verifies the full key against each stored hash; if none verify, the request is rejected with 401 before any DB user is resolved. Note that the presented key may exist but be revoked (revoked_at IS NULL filter), which yields the same error.

Source

Thrown at cli/node/src/backend/platform.ts:68

		const headers = {
			...this.headers,
			"X-Mem0-Caller-Type": isAgentMode() ? "agent" : "user",
		};

		const fetchOpts: RequestInit = {
			method,
			headers,
			signal: AbortSignal.timeout(30_000),
		};
		if (opts?.json) {
			fetchOpts.body = JSON.stringify(opts.json);
		}

		const resp = await fetch(url, fetchOpts);

		if (resp.status === 401) {
			throw new AuthError();
		}
		if (resp.status === 404) {
			throw new NotFoundError(path);
		}
		if (resp.status === 400) {
			let detail: string;
			try {
				const body = (await resp.json()) as Record<string, unknown>;
				detail =
					((body.detail ?? body.message ?? JSON.stringify(body)) as string) ??
					resp.statusText;
			} catch {
				detail = resp.statusText;
			}
			throw new APIError(path, detail);
		}
		if (!resp.ok) {
			let detail: string = resp.statusText;

View on GitHub (pinned to 001c235229)

Solutions

  1. Generate a new API key via POST /api-keys while authenticated (Bearer token or ADMIN_API_KEY) and use the full returned key value — it is only shown once.
  2. If the key should still be valid, check it was not revoked: inspect api_keys.revoked_at in the server DB or the key listing endpoint.
  3. Verify the key belongs to this deployment's database (keys are per-instance, not global) and that ADMIN_API_KEY, if set, is being sent verbatim when you intend to use the admin path.
  4. Strip whitespace/newlines from the header value in the client; confirm you send the raw key, not its prefix or a hashed form.

Example fix

# before
response = requests.get("http://server:3000/memories", headers={"X-API-Key": key_prefix})

# after
response = requests.get("http://server:3000/memories", headers={"X-API-Key": full_key.strip()})
Defensive patterns

Strategy: try-catch

Validate before calling

import re

def is_plausible_api_key(key: str) -> bool:
    # full keys are long; prefixes alone will never authenticate
    return bool(key) and len(key.strip()) >= 20 and not key.startswith("Bearer ")

Type guard

def assert_valid_api_key(key: str | None) -> None:
    assert isinstance(key, str) and len(key.strip()) >= 20, \
        "expected full API key (not the prefix); generate one via POST /api-keys"

Try / catch

resp = requests.get(url, headers={"X-API-Key": key})
if resp.status_code == 401 and resp.json().get("detail") == "Invalid API key.":
    # regenerate the key via an authenticated admin session; do NOT blind-retry
    raise CredentialsError("API key invalid or revoked; rotate it")

Prevention

When it happens

Trigger: Any request with an X-API-Key header whose value is wrong, truncated, revoked, or belongs to another deployment. Concretely: calling GET /memories with a key you just revoked via DELETE /api-keys/{id}; copying only the visible prefix instead of the full key returned at creation; using a key from a different server/database; sending the key when ADMIN_API_KEY is set but the value does not match it (it then falls through to the API-key table lookup).

Common situations: Key was revoked but the client cached it; the full key was only shown once at creation and was lost, so the client uses a placeholder; the server database was reset/redeployed so old keys no longer exist; a typo or whitespace/newline introduced when copying the key into an env var or CI secret.

Understand the failure class

Related errors


AI-assisted analysis of mem0ai/mem0@001c235229 (2026-08-15). Data as JSON: /api/errors/454f0f3657f4ec79. Report an issue: GitHub.