bytedance/deer-flow · error · HTTPException

invalid_credentials

invalid_credentials

Error message

Incorrect email or password

What it means

401 from POST /api/auth/login: the local provider's authenticate() returned None — no user with that email exists or the password hash does not verify. The response body is a structured AuthErrorResponse with code 'invalid_credentials', and the failure is recorded against the client IP for the rate limiter.

Source

Thrown at backend/app/gateway/routers/auth.py:303

# ── Endpoints ─────────────────────────────────────────────────────────────


@router.post("/login/local", response_model=LoginResponse)
async def login_local(
    request: Request,
    response: Response,
    form_data: OAuth2PasswordRequestForm = Depends(),
    remember_me: bool = Form(default=True),
):
    """Local email/password login."""
    client_ip = _get_client_ip(request)
    _check_rate_limit(client_ip)

    user = await get_local_provider().authenticate({"email": form_data.username, "password": form_data.password})

    if user is None:
        _record_login_failure(client_ip)
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail=AuthErrorResponse(code=AuthErrorCode.INVALID_CREDENTIALS, message="Incorrect email or password").model_dump(),
        )

    _record_login_success(client_ip)
    token = create_access_token(str(user.id), token_version=user.token_version)
    _set_session_cookie(response, token, request, remember_me=remember_me)

    return LoginResponse(
        expires_in=get_auth_config().token_expiry_days * 24 * 3600,
        needs_setup=user.needs_setup,
    )


def _local_registration_enabled() -> bool:
    """Whether visitors may self-register a local account.

    Local registration bypasses the OIDC provisioning policy entirely

View on GitHub (pinned to 1dd6ba1acb)

Solutions

  1. Verify the email is registered locally (or use the password-reset flow) and retype the password
  2. If the account is OAuth-only, log in via the SSO provider instead of local credentials
  3. Administrators can reset the user's password in the user store to restore local login
  4. Distinguish from lockout: 401 means credentials wrong; 429 means locked out
Defensive patterns

Strategy: try-catch

Try / catch

try { await login(email, password); } catch (e) {
  if (e.status === 401 && e.body?.code === 'invalid_credentials') { showCredentialError(); return; }
  throw e;
}

Prevention

When it happens

Trigger: POST /api/auth/login (OAuth2 form: username=email, password) with an unregistered email, a wrong password, or a user record whose password_hash does not match. Also when the user was created via OAuth and has no local password.

Common situations: Password reset not yet applied; user registered through SSO but attempts email/password login; stale token_version or migrated user store with un-migrated hashes; typos in email.

Related errors


AI-assisted analysis of bytedance/deer-flow@1dd6ba1acb (2026-08-14). Data as JSON: /api/errors/7fd611a176bcf403. Report an issue: GitHub.