Skip to content

Process gap: admin panel JS errors not caught before prod deploy #198

Description

@sacha-l

What broke in production (post-#195 deploy)

Two errors surfaced in the browser console after merging the results panel to main:

1. Uncaught InvalidStateError — Recharts 0-width canvas (fixed in #196 / #197)

Failed to execute 'createPattern' on 'CanvasRenderingContext2D':
The image argument is a canvas element with a width or height of 0.

Root cause: ResponsiveContainer fired its first resize tick with width=0 while the admin panel layout was still in transition (CSS expansion on wallet unlock). Recharts tried to paint a Canvas gradient onto a 0×0 element.

2. Transient CORS block on GET /api/programs/bitrefill-2026 (no code change needed)

Response to preflight request doesn't pass access control check:
No 'Access-Control-Allow-Origin' header is present on the requested resource.

Root cause: Railway container-swap gap during deploy — old container went down before the new one was serving. stadium.joinwebzero.com was in the CORS allowlist the whole time. Resolved itself within minutes.


Why the gaps exist

Gap 1 — Mock mode hides layout-transition timing

stadium-tester runs in mock mode (VITE_USE_MOCK_DATA=true). In mock mode the admin panel is immediately visible before any data loads, so the chart always gets a non-zero measured width on first render. The production path (wallet unlock → panel CSS transition → chart mounts mid-transition) never fires in the test harness.

Fix idea: add a post-unlock page.waitForTimeout(200) + page.evaluate(() => window.__consoleErrors) assertion step to the dev:harness spec to catch errors that fire during mount, not just during expect() assertions. Or add an explicit invariant: after rendering ProgramResultsSummarySection, assert no InvalidStateError in the console.

Gap 2 — No post-deploy smoke test on production

After Railway auto-deploys from a main push, there is no automated check that:

  • The server responds to a CORS preflight from stadium.joinwebzero.com
  • The client JS loads without throwing on first render

The CORS error was caught manually, not by tooling.

Fix idea: add a lightweight npm run verify:deploy script (extending the existing verify:production) that:

  1. Hits OPTIONS /api/programs/bitrefill-2026 from an origin header of https://stadium.joinwebzero.com and asserts Access-Control-Allow-Origin is present
  2. Could be wired as a Railway deploy webhook or a GitHub Actions step on push to main

Gap 3 — Recharts zero-width is a known footgun, not documented

The createPattern error is a well-known Recharts 2.x issue. Every future use of ResponsiveContainer risks hitting it. Not currently called out in CLAUDE.md or the improvement backlog.

Fix idea: Add a one-liner to CLAUDE.md §4 invariants: "Any <ResponsiveContainer> must include debounce={50} and style={{ minWidth: 1 }} — Recharts fires its first resize tick at width=0 during layout transitions and throws a Canvas error."


Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    claude-suggestedIssue suggested by the Claude agent during a /ship-issue run

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions