mem0ai/mem0 · error · NotFoundError
Resource not found: ${path}
Error message
Resource not found: ${path} What it means
POST /auth/login looked up the submitted email and found no user row, so it returns the generic 401 'Invalid email or password'. A dummy bcrypt verify (dummy_verify_password) is executed first to keep response timing comparable to the wrong-password case, preventing user-enumeration via timing. The email not existing and the password being wrong are deliberately indistinguishable.
Source
Thrown at integrations/openclaw/backend/platform.ts:62
url += `?${qs}`;
}
const fetchOpts: RequestInit = {
method,
headers: this.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;
try {
const body = (await resp.json()) as Record<string, unknown>;
detail = (body.detail ?? body.message ?? resp.statusText) as string;View on GitHub (pinned to 001c235229)
Solutions
- Confirm an account exists: on a fresh instance complete /setup (POST /auth/register) first; otherwise verify the email with the admin's user list.
- Check you are hitting the correct server BASE_URL/environment.
- Use the exact email used at registration; if the DB was reset, re-register and re-issue credentials.
- If access is truly lost and no admin remains, an operator with DB access can remove users to reopen /setup.
Example fix
# before
login("admim@example.com", pw) # typo -> 401
# after
login("admin@example.com", pw) Defensive patterns
Strategy: validation
Validate before calling
import re
EMAIL_RE = re.compile(r"^[^\s@]+@[^\s@]+\.[^\s@]+$")
def validate_login(email: str, password: str) -> None:
if not EMAIL_RE.match(email or ""):
raise ValueError(f"Not a valid email: {email!r}")
if not password:
raise ValueError("Password is empty") Type guard
def looks_like_email(value: str | None) -> bool:
return isinstance(value, str) and "@" in value and "." in value.split("@")[-1] Try / catch
if resp.status_code == 401 and resp.json().get("detail") == "Invalid email or password.":
# do NOT distinguish wrong-email vs wrong-password; re-verify against the intended environment
raise CredentialsError("Check email/password and that BASE_URL targets the right instance") Prevention
- Verify /auth/setup-status shows setup complete before adding login to flows.
- Pin BASE_URL per environment so credentials are never sent to the wrong one.
- Store the registered email exactly (watch local-part case).
When it happens
Trigger: Logging in before registering (users table empty or email absent); typo/case mismatch in the email (EmailStr normalizes the domain but the lookup is exact); logging in against the wrong environment (dev vs prod) or after a DB reset removed users.
Common situations: Fresh deployment where /setup was never completed; environment mismatch in scripts (BASE_URL pointing at another instance); email entered with different capitalization in the local part; database volume recreated so all accounts vanished.
Related errors
- Bad request to ${path}: ${detail}
- Authentication failed. Your API key may be invalid or expire
- Resource not found: ${path}
- Bad request to ${path}: ${detail}
- Either memoryId or --all is required
AI-assisted analysis of mem0ai/mem0@001c235229 (2026-08-15).
Data as JSON: /api/errors/8aaf9f04db6e84a6.
Report an issue: GitHub.