Files
microfish/docs/engineering-log/2026-09-01-login-white-screen.md
2026-09-01 12:19:23 +07:00

3.1 KiB
Raw Blame History

2026-09-01 — Production Login White-Screen Root Cause

Status

Root cause fixed locally; fresh review and production redeploy pending.

Incident

Production redirected unauthenticated users to /login, then rendered a blank page. The browser console reported:

SyntaxError: 10
... nextToken -> parse

Earlier hypotheses around cache, gzip transport, stale assets, and minified line length were disproved: the served JavaScript asset matched the local build byte-for-byte and passed node --check.

Verified root cause

LoginView.vue renders t('auth.emailPlaceholder'). Both locales/th.json and locales/en.json contained:

"emailPlaceholder": "name@company.com"

vue-i18n treats @ as linked-message syntax. Direct compiler reproduction returned:

code 10: Invalid linked format
code 14: Unexpected lexical analysis
code 13: Unexpected empty linked key

A RED regression test that compiles every Thai and English message failed specifically at th:auth.emailPlaceholder, matching production error code 10.

Fix

  • Escape the literal at-sign using vue-i18n syntax: name{'@'}company.com in both locales.
  • Add a regression contract test that translates every string in both language dictionaries through vue-i18n's public createI18n/global.t API (recursing nested objects and arrays) and asserts the placeholder renders as name@company.com.

The rendered translation remains name@company.com.

Verification

  • RED focused test: failed at th:auth.emailPlaceholder with code 10 before the fix.
  • Reviewer cycle 1 failed closed because the initial compiler test skipped strings nested inside locale arrays and used an internal compiler package. The test was corrected to recurse arrays, use vue-i18n's public createI18n/global.t API, and assert the visible placeholder value.
  • Reviewer cycle 2 failed closed on a stale doc line (it still referenced the internal compiler package); the doc was corrected and the placeholder assertion moved inside the per-locale loop (fix-forward push 0359856).
  • Final independent reviewer returned passed: true with empty security_concerns, logic_errors, and suggestions, confirming the reproduction, the fix, the public-API regression, array/object recursion, and all 11 tests + production build.
  • Frontend tests: 11 passed, 0 failed.
  • Production build: 699 modules, index-B4oVHpLg.js, build passed.
  • Chrome headless rendered DOM from the production build contains login-card, เข้าสู่ระบบ CrowdSight, and name@company.com.
  • Browser runtime log contained no SyntaxError or uncaught exception.
  • Screenshot file was produced at 1280×800, but image-model analysis was unavailable because the configured vision provider returned HTTP 401; this remains an explicit visual-analysis gap.
  • git diff --check: passed.
  • Static dangerous-pattern scan on added lines: no findings.

Remaining

  1. Obtain a fresh independent reviewer verdict on the current diff.
  2. Commit/push after review.
  3. Rebuild EasyPanel and verify live /login uses the fresh chunk and renders visibly.
  4. Mobile visual QA remains deferred as previously agreed.