fix(frontend): stop spurious raw-app reload that 404s on "Start without AI" (#10099)

* fix(frontend): stop spurious raw-app reload that 404s on "Start without AI"

Creating a new raw app and clicking "Start without AI" surfaced an "App not
found" toast. The page's load effect re-ran loadApp() mid-bootstrap and fetched
the draft via getAppByPath before the first autosave POST had landed → 404.

Root cause: the effect used the legacy run() from svelte/legacy without
untrack, so loadApp()'s synchronous reactive read of the draft-hint SvelteMap
(getLocalDraftHint via shouldSeedNewDraft, added in #10044) subscribed the
effect. The first autosave optimistically flips that hint (#9351) before its
debounced POST, re-firing the effect → spurious loadApp() → getAppByPath on a
not-yet-persisted draft.

Convert the block to $effect + untrack so it depends only on page.params.path /
$workspaceStore, matching the sibling apps/edit and flows/edit routes. Autosave
and draft persistence are unchanged; only the phantom reload is removed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* chore(frontend): tighten untrack invariant comment to ≤4 lines

Per AGENTS.md comment policy (Codex review nit).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Guilhem
2026-07-14 19:02:22 +02:00
committed by GitHub
parent cfc3f292ad
commit 2c702efec0
@@ -1,6 +1,5 @@
<script lang="ts">
import { run } from 'svelte/legacy'
import { onDestroy } from 'svelte'
import { onDestroy, untrack } from 'svelte'
import { stripNewDraftFlag, stripNewDraftFlagOnSave, shouldSeedNewDraft } from '$lib/newDraftFlag'
import { AppService } from '$lib/gen'
@@ -419,16 +418,22 @@
}
}
run(() => {
$effect(() => {
// Re-run on workspace OR path change so navigating from one raw app editor
// to another (e.g. via the workspace picker) reloads the new app.
const currentPath = page.params.path
if ($workspaceStore && currentPath !== undefined) {
// Clear files so RawAppEditor unmounts; it will remount when loadApp
// completes with fresh data, re-initializing its internal stores.
files = undefined
path = currentPath
loadApp()
// untrack so loadApp's reactive reads (the draft-hint SvelteMap via
// shouldSeedNewDraft) don't subscribe this effect — else the first
// autosave's optimistic hint flip re-fires loadApp mid-bootstrap and
// 404s on the not-yet-POSTed draft. Depend only on path/workspace above.
untrack(() => {
// Clear files so RawAppEditor unmounts; it remounts when loadApp
// completes with fresh data, re-initializing its internal stores.
files = undefined
path = currentPath
loadApp()
})
}
})