OpenBB-finance/OpenBB · error · ValueError

Invalid username or password.

Error message

Invalid username or password.

What it means

Raised when the base64 token decodes cleanly but the username or password does not match the server_auth credentials, compared with secrets.compare_digest for timing safety. It surfaces as HTTP 401 with this detail. Credentials are wrong or stale — the request format was correct.

Source

Thrown at openbb_platform/extensions/mcp_server/openbb_mcp_server/app/auth.py:65

        try:
            scheme, token = auth_header.split()
            if scheme.lower() != "bearer":
                raise ValueError("Invalid authentication scheme.")

            try:
                decoded = base64.b64decode(token).decode("utf-8")
                username, password = decoded.split(":", 1)
            except (binascii.Error, ValueError) as e:
                raise ValueError("Invalid base64-encoded token.") from e

            expected_username, expected_password = self.server_auth

            is_user_valid = secrets.compare_digest(username, expected_username)
            is_pass_valid = secrets.compare_digest(password, expected_password)

            if not (is_user_valid and is_pass_valid):
                raise ValueError("Invalid username or password.")

            request.state.user = {"username": username}
        except (ValueError, HTTPException) as e:
            detail = getattr(e, "detail", str(e))
            raise HTTPException(
                status_code=401,
                detail=detail,
                headers={"WWW-Authenticate": "Bearer"},
            ) from e

        return True

    async def verify_token(self, token: str) -> AccessToken | None:
        """Verify the token."""
        if not self.server_auth:
            return None

        try:

View on GitHub (pinned to 3e071fcc2c)

Solutions

  1. Verify the exact username/password pair configured as the server's server_auth.
  2. Regenerate the token after fixing credentials, trimming stray whitespace/newlines before encoding.
  3. Rotate/update the client's stored credentials if the server pair changed.
  4. Confirm you are pointing at the intended environment (dev vs prod server_auth).

Example fix

# before (password with trailing newline from file read)
pw = open("pw.txt").read()  # "secret\n"

# after
pw = open("pw.txt").read().strip()
token = base64.b64encode(f"{user}:{pw}".encode()).decode()
Defensive patterns

Strategy: retry

Validate before calling

def verify_credentials(candidate_user: str, candidate_pass: str, server_auth: tuple[str, str]) -> bool:
    import secrets
    u, p = server_auth
    return secrets.compare_digest(candidate_user.strip(), u) and secrets.compare_digest(candidate_pass.strip(), p)

Try / catch

for attempt, (user, pw) in enumerate(credential_sources):
    try:
        session.headers["Authorization"] = f"Bearer {make_bearer_token(user, pw)}"
        await client.call_tool("list_categories", {})
        break
    except Exception as e:
        if "Invalid username or password" not in str(getattr(e, "detail", e)) or attempt == len(credential_sources) - 1:
            raise

Prevention

When it happens

Trigger: Typo in username or password; credentials rotated on the server but the client still caches the old pair; environment-specific credentials (dev vs prod) mixed up; whitespace accidentally included when building the token.

Common situations: Stale .env values after a password rotation; CI using expired test credentials; trailing newline in a password read from a file and included in the base64 payload.

Related errors


AI-assisted analysis of OpenBB-finance/OpenBB@3e071fcc2c (2026-08-14). Data as JSON: /api/errors/0e01e3a84dde6f99. Report an issue: GitHub.