Address reviewer round-2 fail-closed feedback on 333f6cc:
- Incident doc no longer claims the regression uses @intlify/message-compiler
baseCompile; it states the regression uses vue-i18n's public createI18n/
global.t API recursing nested objects and arrays.
- The placeholder render assertion now runs inside the locale loop, so both
Thai and English are each explicitly asserted to render name@company.com
(previously only the final English locale was asserted after the loop).
Verified: frontend tests 11 passed; production build index-B4oVHpLg.js passed.
2.7 KiB
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.comin both locales. - Add a regression contract test that translates every string in both language dictionaries through vue-i18n's public
createI18n/global.tAPI (recursing nested objects and arrays) and asserts the placeholder renders asname@company.com.
The rendered translation remains name@company.com.
Verification
- RED focused test: failed at
th:auth.emailPlaceholderwith 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.tAPI, and assert the visible placeholder value. - 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, andname@company.com. - Browser runtime log contained no
SyntaxErroror 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
- Obtain a fresh independent reviewer verdict on the current diff.
- Commit/push after review.
- Rebuild EasyPanel and verify live
/loginuses the fresh chunk and renders visibly. - Mobile visual QA remains deferred as previously agreed.