You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Because [org]/[proj]/[id] is a catch-all 3-segment matcher, this fires for any unmatched 3-segment path — not just real projects — and the redirect is a permanent, browser-cacheable 301. That combination is a recurring footgun.
Why it's a problem
Collides with any 3-segment path. A missing static asset under a 3-segment
URL (e.g. /templates/slides/index.json) falls through to this route and is
redirected to …/data instead of returning a clean 404.
/…/<file>/data → 500, not 404. The redirected path is then resolved as a
static file: Next stats public/…/<file>/data, which throws ENOTDIR when <file> is a real file (Next's static handler only anticipates ENOENT) →
unhandled 500.
Permanent 301 = cached wedge. The 301 carries no Cache-Control, so
Chromium/Electron caches it indefinitely. Once a client sees it (while the
asset was momentarily missing), it keeps following the cached redirect to …/data → 500 without ever re-requesting the now-present asset. Only a
cache clear recovers it.
Evidence
Bit the desktop slides gallery in feat(desktop): slides template workflow for agent-authored decks #949: a not-yet-materialized /templates/slides/index.json → 301 → …/data → ENOTDIR 500, and then the
cached 301 kept the error alive in the desktop renderer after the file existed
(recovered only by clearing the network cache).
This is not the first time this catch-all /data redirect has produced
surprising behavior — it's a recurring bad design, not a one-off.
The ask (later, focused — does not block current work)
Carefully rework or drop the universal /data redirect. Directions to weigh:
Scope the match to real projects — validate that org/proj/id resolve
before redirecting, so arbitrary 3-segment paths fall through to a normal 404
instead of being absorbed.
If the redirect stays, make it non-permanent (302/307) so a stale mistake
can't wedge a browser cache.
Avoid the catch-all route handler entirely for "bare project URL → default
tab" — e.g. render the default tab, or redirect from inside the already-
validated layout.tsx (which does the org/proj/doc lookups anyway).
Care needed: this drives the real /{org}/{proj}/{id} → /{org}/{proj}/{id}/data
behavior for actual projects. The fix must preserve that while removing the
catch-all collision — a focused pass, not a drive-by.
Summary
editor/app/(workbench)/[org]/[proj]/[id]/route.tsunconditionally 301-redirectsany
/{a}/{b}/{c}path to/{a}/{b}/{c}/data:Because
[org]/[proj]/[id]is a catch-all 3-segment matcher, this fires forany unmatched 3-segment path — not just real projects — and the redirect is a
permanent, browser-cacheable 301. That combination is a recurring footgun.
Why it's a problem
URL (e.g.
/templates/slides/index.json) falls through to this route and isredirected to
…/datainstead of returning a clean 404./…/<file>/data→ 500, not 404. The redirected path is then resolved as astatic file: Next stats
public/…/<file>/data, which throwsENOTDIRwhen<file>is a real file (Next's static handler only anticipatesENOENT) →unhandled 500.
Cache-Control, soChromium/Electron caches it indefinitely. Once a client sees it (while the
asset was momentarily missing), it keeps following the cached redirect to
…/data→ 500 without ever re-requesting the now-present asset. Only acache clear recovers it.
Evidence
/templates/slides/index.json→ 301 →…/data→ENOTDIR500, and then thecached 301 kept the error alive in the desktop renderer after the file existed
(recovered only by clearing the network cache).
/dataredirect has producedsurprising behavior — it's a recurring bad design, not a one-off.
The ask (later, focused — does not block current work)
Carefully rework or drop the universal
/dataredirect. Directions to weigh:org/proj/idresolvebefore redirecting, so arbitrary 3-segment paths fall through to a normal 404
instead of being absorbed.
can't wedge a browser cache.
tab" — e.g. render the default tab, or redirect from inside the already-
validated
layout.tsx(which does the org/proj/doc lookups anyway).Care needed: this drives the real
/{org}/{proj}/{id}→/{org}/{proj}/{id}/databehavior for actual projects. The fix must preserve that while removing the
catch-all collision — a focused pass, not a drive-by.