Skip to main content
Resolved · INC-2026-08-15-01

Production Outage — Server Bundle Failed To Boot

The published site and every signed-in workspace returned a server error. No customer data was lost, altered, or exposed: the failure was in the server bundle that renders pages, not in the database or its access policies.

Date
08-15-2026
Window
8:42 PM – 1:14 AM CT
Duration
4 hours 32 minutes
Data Impact
None — no data loss, corruption, or unauthorized access.

What Went Wrong

A markdown renderer and a browser-only charting library were reachable from a server-rendered route module. The production worker evaluates every route module at boot, so the bad import chain took down the whole bundle rather than one page. A stale cached service worker then kept serving the broken shell to browsers after the fix shipped, which is why recovery took a second publish and a cache purge.

Severity: Sev-1 — full public outage · Reported by: Owner (Joe Barnhill) after a failed page load on the published site

Step-By-Step Timeline

Every failure, diagnosis, fix, publish, and cache refresh, in the order it happened. Times are Central and elapsed markers count from the first failed request.

  1. T+0mFailureSite Offline

    Publish Completes, Server Bundle Fails To Boot

    A publish finished successfully at the build step, but the production worker could not evaluate its server bundle. Every route, including the marketing home page, began returning a server error.

    500 on GET / — worker boot error, no route handlers registered

    Result
    Public site offline. Start of the outage window.
  2. T+9mDetectionSite Offline

    Outage Confirmed From Two Independent Signals

    A failed page load was reported by the owner and independently confirmed against the health endpoint from outside the network.

    GET /healthz — 500 (expected 200 ok)

    Result
    Incident opened; investigation moved to the server boot path.
  3. T+26mDiagnosisSite Offline

    Failure Isolated To Server-Side Module Evaluation

    Local development still worked because the dev server evaluates modules lazily. Reproducing against a production build surfaced the real error at boot instead of at request time.

    ReferenceError: window is not defined — during route module evaluation

    What Changed
    Ran a production build locally and imported each route module in isolation.
    Result
    Two offending import chains identified in server-rendered route modules.
  4. T+55mFixSite Offline

    Markdown Renderer Moved Behind A Client-Only Boundary

    The markdown renderer used by help and guide pages was imported at module scope, so the server evaluated it on boot. It now loads lazily in the browser only.

    What Changed
    Converted the renderer to a lazy import behind a client-only wrapper.
    Result
    First of two boot failures cleared in the local production build.
  5. T+1h 20mFixSite Offline

    Browser-Only Chart Library Removed From The Server Path

    A dashboard chart module pulled a browser-only library into a shared utility that server-rendered routes imported. Shared values were split into a server-safe module so the heavy library stays on the client.

    What Changed
    Split shared constants and types out of the chart module; charts now load after hydration.
    Result
    Local production build booted cleanly for the first time.
  6. T+1h 39mPublish / Cache RefreshSite Offline

    First Recovery Publish

    The two fixes were published together. The server came back, but browsers with a previously cached service worker still rendered a broken shell.

    GET /healthz — 200 ok; hard-reloaded browsers fine, returning browsers still broken

    What Changed
    Published the fixed build to production.
    Result
    Server healthy, but returning visitors still saw the failure.
  7. T+2h 2mDiagnosisSite Offline

    Stale Service Worker Identified As The Second Failure

    The offline cache was serving the pre-outage application shell and its now-missing asset URLs, so a healthy server still produced a blank page for anyone who had visited before.

    Workbox: precache entry not found — cached shell references removed asset hashes

    Result
    Recovery required a cache-invalidating publish, not just a code fix.
  8. T+2h 27mFixSite Offline

    Service Worker Given A New Revision And Self-Retirement Path

    The cache revision was bumped, oversized entries that had been silently failing to precache were dropped, and the worker now claims clients and deletes caches from older revisions on activation.

    What Changed
    Bumped the precache revision, reduced the precache budget, and enabled skip-waiting plus old-cache cleanup.
    Result
    Returning browsers now discard the broken shell on their first request.
  9. T+2h 49mPublish / Cache RefreshSite Reachable

    Second Recovery Publish And Edge Cache Purge

    The new build was published and the edge cache was purged so that the HTML document and the service worker script were both refetched from origin rather than served from an intermediate cache.

    What Changed
    Published, then purged the cached HTML and service-worker responses.
    Result
    Fresh and returning browsers both loaded the working site.
  10. T+3h 10mVerificationSite Reachable

    Route-By-Route Boot Verification Added

    A diagnostic endpoint was added that imports every server-rendered route module and reports any that fail to evaluate or that pull in a browser-only library — turning this class of outage into a pre-publish check instead of a post-publish surprise.

    GET /routesz — all route modules evaluated, no browser-only leaks

    What Changed
    Added the /routesz boot probe behind a shared secret.
    Result
    The failure mode is now detectable before a publish goes out.
  11. T+3h 44mVerificationSite Reachable

    Signed-In Paths And Workspace Data Confirmed Intact

    Sign-in, workspace switching, the ledger, invoices, and reconciliation were exercised on the published site. Record counts matched pre-outage values and access policies behaved as expected.

    Result
    No data loss and no cross-workspace exposure.
  12. T+4h 32mVerificationSite Reachable

    Incident Closed After A Clean Observation Window

    Health checks, the route boot probe, and a post-publish smoke test all passed repeatedly with no recurrence, and the incident was closed.

    Post-publish smoke test — all checks passed

    Result
    Service fully restored. Total outage: 4 hours 32 minutes.

What Changed Afterward

The safeguards added so this class of failure is caught before a publish reaches you.

  • Route Boot Probe In Every Publish

    In Place

    The /routesz probe runs as part of the post-publish smoke test, so a server bundle that cannot boot is caught immediately.

  • Cache Revision Tied To Each Build

    In Place

    The offline cache revision changes with every build, so a new publish can never be shadowed by an old cached shell.

  • Production Build Check Before Publishing

    In Place

    Server-side rendering is exercised against a production build, not only the development server, because the development server hides boot-time failures.

  • Automated External Uptime Alert

    Planned

    An outside monitor pinging the health endpoint on a short interval so detection does not depend on someone loading a page.

Questions about this incident, or want the same detail for a future one? See Security & Trust for how we handle notification and review, or reach us through the security contact form there.