ReviewOS

stacks/stx

fix(serve): deleting a page file while the dev server runs leaves a 500 route instead of falling back

#2131
Closed glennmichael123 opened this 5 days ago ·
5 days ago

Problem

When serve() has two page patterns that both provide a page (an app's override first, the framework's default second), deleting the app's file while the dev server runs makes that route answer 500 Internal Server Error until the server restarts. It should fall back to the next pattern's page, or 404 if none has it.

Components don't have this problem: deleting an app's override component while the server runs falls back to the framework's on the next request.

Reproduction (Stacks system tray, stx 0.2.733)

buddy dev:system-tray serves patterns: [<app>/resources/views/system-tray, <framework>/views/system-tray].

  1. Create resources/views/system-tray/index.stx in the app (a copy of the framework's, with a marker).
  2. Start the server. GET / returns 200 with the app's marker.
  3. Delete resources/views/system-tray/ while the server runs. GET / now returns 500 with the generic "Internal Server Error" body.
  4. Restart the server with the file still absent. GET / returns 200 with the framework's page (21,908 bytes, no marker).

So the framework page is resolvable. The route discovered at startup keeps pointing at the deleted file.

Expected

A .stx deletion under a pattern directory invalidates that route, and the next request resolves through the remaining patterns, as a server restart would. The watcher already sees the event: pattern directories are watched for cache invalidation.

Why it matters

Stacks apps now override framework pages by copying them into the app (buddy publish:view, stacksjs/stacks#3032). Removing an override to return to the framework's page is a normal step, and today it looks like the page broke.

5 days ago

Fixed on main in b756671 (after v0.2.735; not part of that release). Directory rename/removal now invalidates page discovery and render caches, parent-entry watchers survive deleting/recreating a page root, and middleware ownership is rebuilt before guards run. This fixes route resolution rather than catching or translating a rendering 500.

Regression coverage: packages/bun-plugin/test/serve-page-deletion.test.ts exercises file deletion, nested-directory deletion, whole-root deletion and moving the root, framework fallbacks, a real 404 when no fallback exists, guarded fallback pages, and recreation/editing without restart. Reproduced the original 500 before the fix; temporarily removing middleware refresh also makes three security regressions fail.

Verification: 369 Bun-plugin tests passed, 0 failed; release preflight passed (including 324 tests), typecheck, lint and format checks passed. A normal patch release follows once v0.2.735 finishes publishing; I will add the exact published version here after registry verification.

5 days ago

Published and verified: @stacksjs/stx, bun-plugin-stx, and @stacksjs/components 0.2.736. The fix is b756671; v0.2.735 and its layout fix are preserved unchanged.

The exact tagged release gate passed: 17,326 tests passed, 46 skipped, 0 failed across 1,390 files. All four deletion/recreation regressions in packages/bun-plugin/test/serve-page-deletion.test.ts passed. Release-commit CI and latest-main CI are green.

Separately verified a fresh npm install of the exact 0.2.736 packages (not workspace sources): additional component-root edits emit fragment HMR, moving away the app page root serves the framework fallback, the fallback middleware prevents protected content from leaking, and recreating/editing the app override works without restarting.

Stacks needs only its normal STX version bump; no Stacks code change or 500-to-404 workaround is needed for this fix.

Sign in to comment on this issue.