QuantumNous/new-api · error · Error
Login failed
Error message
Login failed
What it means
Thrown in the sign-in form when a successful, non-2FA login response fails the isAuthBundle structural check — res.data lacks the required auth bundle fields (access token, session, user). It protects handleLoginSuccess from persisting a malformed bundle that would immediately break authenticated requests.
Source
Thrown at web/src/features/auth/sign-in/components/user-auth-form.tsx:187
try {
const res = await login({
username: data.username,
password: data.password,
turnstile: submittedTurnstileToken,
})
if (res.success) {
if (res.data && 'require_2fa' in res.data && res.data.require_2fa) {
if (!res.data.flow_token) {
throw new Error(t('Login flow expired. Please sign in again.'))
}
setPending2FAFlowToken(res.data.flow_token)
redirectTo2FA()
return
}
if (!isAuthBundle(res.data)) {
throw new Error(t('Login failed'))
}
await handleLoginSuccess(res.data, redirectTo)
toast.success(t('Welcome back!'))
}
} catch (error: unknown) {
if (axios.isAxiosError(error)) return
toast.error(error instanceof Error ? error.message : loginFailedMessage)
} finally {
setIsLoading(false)
}
}
const handleOpenWeChatDialog = () => {
if (requiresLegalConsent && !agreedToLegal) {
toast.error(legalConsentErrorMessage)
return
}
View on GitHub (pinned to e2c7aa7b10)
Solutions
- Log res.data shape and compare with isAuthBundle's required fields; the check is the source of truth for the expected contract.
- Align backend login response with the AuthBundle shape (access_token, token_type, access_expires_at, session, user) or update isAuthBundle after a deliberate contract change.
- Check axios response interceptors are not unwrapping/replacing data.
- Ensure frontend/backend deploy together.
Defensive patterns
Strategy: type-guard
Type guard
// isAuthBundle is the guard; keep it authoritative for the login contract
if (res.success && !isAuthBundle(res.data)) { /* contract violation path */ } Try / catch
try {
if (res.success && !isAuthBundle(res.data)) throw new Error(t('Login failed'))
} catch (error) {
if (axios.isAxiosError(error)) return // transport errors handled elsewhere
toast.error(error instanceof Error ? error.message : loginFailedMessage)
} Prevention
- Share one AuthBundle schema between password, 2FA, and passkey login paths
- Pin the backend login response with a consumer-driven contract test
When it happens
Trigger: POST login returns success:true but data is null, partial (missing session/user/token), or an unexpected shape (e.g. only {require_2fa:false}).
Common situations: Backend contract drift after an upgrade (renamed or restructured login payload); response transformed by an interceptor; backend returning success:true on a degraded path without a full bundle.
Related errors
- Missing user data from Passkey login response
- Invalid authentication rotation response
- Unable to parse Passkey login options from response
- Failed to start Passkey login
- Failed to complete Passkey login
AI-assisted analysis of QuantumNous/new-api@e2c7aa7b10 (2026-08-15).
Data as JSON: /api/errors/01666667896013d7.
Report an issue: GitHub.