Skip to content

fix(auth): localize login error message for failed credentials#2890

Open
lawrence3699 wants to merge 1 commit intoChainlit:mainfrom
lawrence3699:fix/login-error-localization
Open

fix(auth): localize login error message for failed credentials#2890
lawrence3699 wants to merge 1 commit intoChainlit:mainfrom
lawrence3699:fix/login-error-localization

Conversation

@lawrence3699
Copy link
Copy Markdown

@lawrence3699 lawrence3699 commented Apr 9, 2026

Summary

Fixes #2873 — follow-up to #2794.

After #2794 fixed the login form to read err.detail instead of err.message, there's still a case sensitivity mismatch that prevents the i18n lookup from working. Users see a raw toast (!) Unauthorized: credentialssignin instead of the translated "Sign in failed. Check the details you provided are correct".

Root cause

Three things conspire:

  1. The backend sends detail="credentialssignin" (all lowercase), but every translation file defines the key as credentialsSignin (camelCase)
  2. LoginForm.tsx applies .toLowerCase() before the i18n lookup, so even a correctly-cased key gets lowercased
  3. The global onError handler in api/index.ts toasts error.toString() for every API error — including 401s on the login page, which the LoginForm already handles with an inline Alert

Changes

  • backend/chainlit/server.py — send credentialsSignin (camelCase) to match the translation keys in all 23 locale files
  • frontend/src/components/LoginForm.tsx — remove .toLowerCase() so the key survives to match the translation
  • frontend/src/api/index.ts — skip toast.error for 401 responses; they're already handled by the login form's inline Alert and the on401 redirect for other pages
  • cypress/e2e/password_auth/spec.cy.ts — update the wrong-credentials assertion to check for the translated message ("Sign in failed") instead of the old raw toast text ("Unauthorized")

Before / After

Before After
Toast (!) Unauthorized: credentialssignin (no toast)
Inline Alert "Unable to sign in" (generic fallback) "Sign in failed. Check the details you provided are correct"

Checks run

  • uv run pytest tests/ — 783 passed
  • pnpm test (frontend) — 32 passed
  • pnpm lint — clean
  • pnpm format-check — clean
  • Pre-commit hooks (lint, format, type-check for Python + TS) — all passed

Summary by cubic

Fixes login error localization for failed credentials so users see the translated inline alert instead of a raw unauthorized toast. Removes the redundant 401 toast and aligns backend/Frontend keys for i18n.

  • Bug Fixes
    • Backend: send credentialsSignin (camelCase) to match translation keys.
    • LoginForm: remove .toLowerCase() so the i18n key matches.
    • API client: skip toast.error for 401 responses; handled by inline Alert and on401.
    • Cypress: update wrong-credentials test to check for "Sign in failed".

Written for commit 3568ccd. Summary will update on new commits.

The backend was sending `detail="credentialssignin"` (all lowercase)
but every translation file defines the key as `credentialsSignin`
(camelCase). The frontend also applied `.toLowerCase()` before the
i18n lookup, guaranteeing the mismatch. On top of that, the global
API error handler was toasting the raw error string for 401 responses,
so users saw `(!) : credentialssignin` instead of the translated
"Sign in failed. Check the details you provided are correct".

Three changes fix this:

1. Backend: send `credentialsSignin` to match translation keys
2. LoginForm: drop `.toLowerCase()` so the camelCase key survives
3. API client: skip `toast.error` for 401s — they're already handled
   by the login form (inline Alert) and the `on401` redirect

Fixes Chainlit#2873

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings April 9, 2026 14:36
@dosubot dosubot bot added size:S This PR changes 10-29 lines, ignoring generated files. auth Pertaining to authentication. translation Translation or localisation of strings. labels Apr 9, 2026
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 4 files

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes the login “wrong credentials” error localization by aligning the backend error detail value and frontend i18n lookup behavior, and by preventing a redundant global toast on 401s.

Changes:

  • Backend now returns detail="credentialsSignin" (camelCase) for failed password auth to match translation keys.
  • Login form no longer lowercases the error key before translation lookup.
  • Global API error handler skips toast.error for 401 responses; Cypress assertion updated for the translated message.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

File Description
backend/chainlit/server.py Aligns 401 login failure detail with existing translation keys (credentialsSignin).
frontend/src/components/LoginForm.tsx Preserves error key casing so t() can resolve auth.login.errors.* entries correctly.
frontend/src/api/index.ts Avoids showing a global toast for 401s (login page handles inline; other pages redirect).
cypress/e2e/password_auth/spec.cy.ts Updates wrong-credentials expectation toward the translated copy (but should more directly assert “no toast + inline alert”).

Comment on lines 29 to 33
cy.get("input[name='email']").type('user');
cy.get("input[name='password']").type('user');
cy.get("button[type='submit']").click();
cy.get('body').should('contain', 'Unauthorized');
cy.get('body').should('contain', 'Sign in failed');
});
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The assertion cy.get('body').should('contain', 'Sign in failed') doesn’t verify the behavior this PR is aiming for (inline Alert is shown and no toast is displayed). Consider asserting on the inline alert element (e.g., .alert) for the translated text, and separately asserting that the toast container (App renders a Toaster with className="toast") does not contain the error / has no toast items, so the test will fail if the global toast reappears.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

auth Pertaining to authentication. size:S This PR changes 10-29 lines, ignoring generated files. translation Translation or localisation of strings.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Login error message is not localized

2 participants