Skip to content

A failed clip fetch behaves in two opposite wrong ways in soglia and stacco #47

Description

@SandroHub013

Same line of code in both video-scrubbing demos, opposite consequences, and both invisible because the error is swallowed:

.catch(() => { s.loading = false; });
  • docs/demos/soglia/app.js:114
  • docs/demos/stacco/app.js:218

soglia — unbounded refetch loop

read() runs on every scroll frame and calls loadClip, whose only guard is:

if (reduce || s.loading || s.ready) return;

Resetting loading = false on failure clears the guard, so the next scroll frame refetches. A clip that 404s or fails to decode becomes an unbounded refetch loop — several MB per attempt, up to once per animation frame, for as long as the visitor keeps scrolling near that segment. On a metered connection that is somebody's data plan.

stacco — permanent silent abandonment

want() guards on one extra flag:

if (reduce || s.loading || s.ready || s.queued) return;
s.queued = true;

s.queued is set to true and never cleared anywhere in the file. So after a single failure the shot is abandoned for good: no retry, no log, and the scene stays on its poster with nothing to indicate anything went wrong.

Why it matters

The two files are the same pattern — stacco evolved from soglia — and they disagree on what failure means. Neither behaviour looks deliberate. The swallowed error is what let them drift apart without anyone noticing.

Suggested fix

A bounded retry in both, sharing one shape:

  • 2–3 attempts with backoff, then stop
  • clear s.queued alongside s.loading in stacco so a retry is actually possible
  • console.warn on the final give-up, naming the clip URL and the status — the poster fallback is fine as an outcome, but it should not be a secret
  • keep the visual behaviour identical: the still stays, the page keeps working

Related, smaller

docs/demos/descent/app.js:316boot().catch() removes the HUD but skips the honest-copy fallback that the !inst branch applies. If data/quakes-2025.bin fails to fetch, the page keeps claiming the scene above is running:

}).catch(() => {
  document.querySelector(".hud")?.remove();
});

The !inst path rewrites .beat--table .beat__body to say the scene is not running. The catch path should do the same.

Found while auditing swallowed errors for #45. Not fixed there — the fix is a behaviour change to two live demos and wants a decision first.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions