Skip to content

fix(web): break effect_update_depth_exceeded in HomePage health-poll diff#40

Merged
explosivebit merged 1 commit into
developfrom
fix/health-effect-loop
May 6, 2026
Merged

fix(web): break effect_update_depth_exceeded in HomePage health-poll diff#40
explosivebit merged 1 commit into
developfrom
fix/health-effect-loop

Conversation

@explosivebit
Copy link
Copy Markdown
Contributor

Summary

Hotfix for runtime error reported by user after F12 merge:

Uncaught Svelte error: effect_update_depth_exceeded
Maximum update depth exceeded. This typically indicates that an effect
reads and writes the same piece of state.

Root cause

HomePage.svelte:130 $effect for breach detection:

  • reads prevHealthSnapshot via detectBreaches(prevHealthSnapshot, next, ...)
  • writes prevHealthSnapshot = next at the bottom

Both on the same $state(...) signal → Svelte 5 (correctly) detects the cycle and abort-loops the effect.

Fix

prevHealthSnapshot is a "previous tick" memo — no template reads it, no other effect depends on it. Reactivity is unnecessary; the value lives across re-runs via the component's closure scope. Demoted to plain let.

Verify

  • npx svelte-check — 0/0/436.
  • npm test — 68/68 (no test impact; pure-function notify lib unchanged).
  • Manual: dev server loads, browser console shows 0 errors after navigation.

Why $state was wrong here

In Svelte 5 runes, $state creates a reactive signal. Any effect that reads + writes the same signal triggers a cycle. For "memoized previous value" between successive runs of one effect, a plain let survives in closure scope without becoming reactive — that's the idiomatic pattern.

Refs: PRD-007 RFC-006

🤖 Generated with Claude Code

…diff

The F12 breach-detection effect read prevHealthSnapshot via
detectBreaches() AND wrote to it (`prevHealthSnapshot = next`) in the
same effect. Since prevHealthSnapshot was declared `$state(...)`,
Svelte 5 (correctly) flagged the cycle as effect_update_depth_exceeded
and stopped re-running the effect.

prevHealthSnapshot is a "previous tick" memo — no template reads it,
no other effect depends on it. Reactivity is unnecessary. Demoting it
to a plain `let` keeps the value alive across effect re-runs through
the component closure scope without making it a reactive signal.

Verify:
- svelte-check 0/0/436.
- npm test 68/68 (no test impact — pure-function notify lib unchanged).
- Manual: dev server loads with no console errors.

Refs: PRD-007 RFC-006
@explosivebit explosivebit merged commit 2c299f7 into develop May 6, 2026
3 checks passed
@explosivebit explosivebit deleted the fix/health-effect-loop branch May 6, 2026 09:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant