Hmbown/CodeWhale · error · Error
World dt must be in [0, 10] seconds.
Error message
World dt must be in [0, 10] seconds.
What it means
step(dt) advances the world by a bounded delta time so a suspended or backgrounded surface cannot trigger an unbounded catch-up simulation when it resumes. dt must be a finite number of seconds in [0, 10]. NaN, Infinity, negatives, or anything above 10 seconds is rejected before the accumulator grows.
Solutions
- Clamp dt before calling: `dt = Math.min(Math.max(dt, 0), 10)`.
- Compute dt from a monotonic clock in seconds and reset the last-timestamp after suspension so the first frame after resume uses a small dt.
- Treat NaN/undefined clock readings as 0 (or skip the frame) instead of forwarding them.
Example fix
// before world.step((now - last) / 1000); // ~5400 after overnight suspend // after let dt = (now - last) / 1000; last = now; dt = Number.isFinite(dt) ? Math.min(Math.max(dt, 0), 10) : 0; world.step(dt);
Defensive patterns
Strategy: validation
Validate before calling
function safeStep(world, dt) {
const d = Number(dt);
if (!Number.isFinite(d) || d < 0 || d > 10) return false;
world.step(d);
return true;
} Type guard
const isFiniteDt = (dt) => typeof dt === 'number' && Number.isFinite(dt) && dt >= 0 && dt <= 10;
Try / catch
try {
world.step(dt);
} catch (e) {
if (e.message.includes('World dt must be')) {
world.step(0); // skip the bad frame rather than crashing the loop
} else throw e;
} Prevention
- Clamp clock deltas to [0, 10] before every step call
- Use a monotonic clock and reset the last timestamp after suspension
- Convert ms to s carefully — performance.now() deltas need /1000
- Treat NaN/undefined dt as 0 or skip the frame
When it happens
Trigger: Calling world.step(dt) with NaN or Infinity (e.g. from a broken clock delta), a negative dt from a clock that jumped backwards, or a huge dt such as the raw elapsed seconds after the tab was suspended overnight.
Common situations: Computing dt as (now - last) after a system sleep or tab suspension; performance.now() units confusion (ms passed where s expected, giving dt=5000); a paused animation frame returning undefined dt; monotonic-clock rollback in VMs.
Related errors
- Invalid Engine pet clock.
- Invalid interval for
- Invalid Runtime retention horizon.
- Signal duration must be finite and nonnegative.
- 1
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/1725bb559f7e8c2c.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/tui/pet_watch/pet-native.js:464
this.hashTape(index);
return;
}
if (sequence >= 216_000)
throw new Error('Archive the legacy recording before accepting more telemetry.');
const changedFrom = Math.min(sequence, this.tapeLog.length);
while (this.tapeLog.length <= sequence) {
const at = this.tapeLog.length;
this.tapeLog.push({ version: 1, sequence: at, simTimeMs: at * 400, durationMs: 400,
activity: .12, coherence: .25, attention: 0, channel: 'other', observed: 0, roamX: 0, roamY: 0, flip: 1, lit: 1,
onsets: Array(13).fill(0), activeMs: Array(13).fill(0), errors: 0, agentIds: [], waiting: false });
}
this.tapeLog[sequence] = { ...structuredClone(input), sequence, simTimeMs: sequence * 400 };
this.hashTape(changedFrom);
}
/** dt is bounded so suspending a surface cannot cause an unbounded catch-up. */
step(dt, opts = { motion: true, sensitivity: 1 }) {
if (!Number.isFinite(dt) || dt < 0 || dt > 10)
throw new Error('World dt must be in [0, 10] seconds.');
this.accumulator += dt;
this.voices = [];
while (this.accumulator + 1e-10 >= 1 / HZ) {
this.accumulator -= 1 / HZ;
const time = ++this.tick / HZ;
this.frame = this.makeFrame(time);
this.voices.push(...this.score.voices(this.frame));
if (!opts.motion) {
this.frame.state = { ...this.frame.state, roamX: 0, roamY: 0, flip: 1, lit: this.behaviour === 'doze' ? .18 : 1 };
this.frame.surface = -.86;
this.frame.caustic = .5;
if (this.frame.food)
this.frame.food.y = this.food.y;
}
const signature = JSON.stringify(this.frame.state);
const peers = this.frame.pod.filter(p => p.present);
const podSlots = peers.length >= 3 ? peers.map(p => [[0, 2, 4, 1, 3, 5][p.slot], p.phase]) : undefined;
if (opts.motion || signature !== this.lastStill || podSlots)View on GitHub (pinned to 73e0f67d83)