mem0ai/mem0 · error · APIError

Bad request to ${path}: ${detail}

Error message

Bad request to ${path}: ${detail}

What it means

POST /auth/login found the user by email but bcrypt verification of the submitted password against the stored hash failed, yielding the same generic 401 as a missing account. Only the exact original password verifies; there is no recovery from the API itself beyond admin-driven reset.

Source

Thrown at integrations/openclaw/backend/platform.ts:74

    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;
      } catch {
        /* ignore */
      }
      throw new Error(`HTTP ${resp.status}: ${detail}`);
    }
    if (resp.status === 204) {
      return {};
    }
    return resp.json();
  }

  async add(

View on GitHub (pinned to 001c235229)

Solutions

  1. Re-enter the correct password carefully (watch for caps-lock/whitespace); .strip() shell-provided values.
  2. If forgotten and another admin exists, have the admin reset it via user management; if it is the only admin, an operator with DB access can set a new hash via the server's hash_password utility.
  3. Update stored secrets/CI variables after any credential rotation and test with a manual login before retrying the pipeline.

Example fix

# before
password=$(cat pw.txt)   # may include trailing newline -> 401
login(email, password)

# after
password=$(cat pw.txt | tr -d '\n')
login(email, password)
Defensive patterns

Strategy: validation

Validate before calling

def validate_login_input(password: str) -> str:
    pw = password.strip()
    if len(pw) < 8:
        raise ValueError("Password shorter than the server minimum of 8; likely truncated or wrong field")
    return pw

Type guard

def is_credential_candidate(password: str | None) -> bool:
    return isinstance(password, str) and len(password.strip()) >= 8

Try / catch

if resp.status_code == 401 and "Invalid email or password" in resp.text:
    if attempt < MAX_ATTEMPTS:
        password = prompt_fresh_password()  # re-collect; never retry the same value blindly
    else:
        raise CredentialsError("Password rejected; rotate via admin reset")

Prevention

When it happens

Trigger: Wrong password (typo, stale credential, changed password); password from a different environment's account; trailing whitespace introduced when pasting the password; credentials rotated by an admin after they were stored in the client.

Common situations: CI secrets holding an old password after an admin reset; password managers auto-filling outdated entries; local dev password differing from the seeded one; copy/paste adding a trailing newline in shell scripts.

Related errors


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