Hmbown/CodeWhale · error · Error
Pet checkpoint telemetry does not match its clock.
Error message
Pet checkpoint telemetry does not match its clock.
What it means
After the cursor check passes, PetWorld re-derives which tape bucket should hold the checkpoint's telemetry: the bucket at bucketIndex whose sim clock window (simTimeMs..simTimeMs+durationMs) contains frame.timeMs. It then compares that bucket (or undefined when the frame falls past the bucket's window) byte-for-byte against the telemetry snapshotted in the checkpoint. A mismatch means the checkpoint's stored telemetry frame was not the one the tape would replay at that time — the checkpoint and the simulation clock disagree.
Solutions
- Take a new checkpoint after accepting or splicing telemetry; do not restore older ones
- Verify the checkpoint's telemetry frame is JSON-identical to world.tape[bucketIndex] for the same timeMs before restoring
- Rebuild the tape from the same recording the checkpoint was made from
- Persist checkpoint and tapeLog together so they cannot diverge
Example fix
// before
world.restoreCheckpoint(cpFromYesterday); // tape bucket since overwritten
// after
const bucket = world.tape[cpFromYesterday.bucketIndex];
if (bucket && JSON.stringify(cpFromYesterday.frame.telemetry) === JSON.stringify(bucket)) {
world.restoreCheckpoint(cpFromYesterday);
} else {
world.restoreCheckpoint(world.checkpoint());
} Defensive patterns
Strategy: validation
Validate before calling
function telemetryMatches(world, c) {
const b = world.tape[c.bucketIndex];
const expected = b && c.frame.timeMs < b.simTimeMs + b.durationMs ? b : undefined;
return JSON.stringify(c.frame.telemetry) === JSON.stringify(expected);
} Try / catch
try {
world.restoreCheckpoint(cp);
} catch (e) {
if (e.message.includes('telemetry does not match')) cp = world.checkpoint();
else throw e;
} Prevention
- Archive the tape together with checkpoints so buckets cannot be overwritten under them
- Re-checkpoint after segmented acceptTelemetry replaces any bucket
- Verify tape/recording identity before restoring a foreign checkpoint
When it happens
Trigger: Restoring a checkpoint whose frame.telemetry was captured from a different tape bucket than bucketIndex — typically after segmented acceptTelemetry spliced/replaced the bucket at that index, after the tape was rebuilt from a different recording, or a checkpoint whose timeMs crosses a bucket boundary that later changed.
Common situations: Accepting corrected live telemetry that overwrote the bucket a checkpoint pointed at; loading checkpoints from a previous recording session; simulating the world independently and restoring into a PetWorld with a different tape history.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- Archive this pet recording before accepting more telemetry.
- Pet checkpoint does not match its recording.
- Pet checkpoint does not match its recording.
- Pet checkpoint does not match its recording.
- Pet checkpoint telemetry does not match its clock.
AI-assisted analysis of Hmbown/CodeWhale@433685b202 (2026-09-15).
Data as JSON: /api/errors/1ea6ccbeeaa9e3fb.
Report an issue: GitHub.
Appendix: source
Thrown at pet/ios/Resources/pet-native.js:386
const world = new PetWorld(points, tape, interactions, c.sim?.expressionVersion ?? 1, c.petCheckpointVersion === 2);
if (c.petCheckpointVersion === 2) {
world.hasTelemetry = c.hasTelemetry;
world.origin = structuredClone(c);
}
if (c.history !== world.historyDigest()
|| c.bucketIndex >= 0 && world.tape[c.bucketIndex].simTimeMs > c.frame.timeMs + 1e-7
// acceptTelemetry may fill past gaps after the most recent fixed tick.
// Preserve that pending cursor exactly; it may lag only over empty gaps.
|| world.tape.some((b, i) => i > c.bucketIndex && b.simTimeMs <= c.frame.timeMs + 1e-7
&& (b.observed !== 0 || b.channel !== 'other' || b.errors || b.waiting || b.agentIds.length
|| b.onsets.some(Boolean) || b.activeMs.some(Boolean)))
|| world.interactionLog.slice(0, c.interactionIndex).some(e => e.timeMs > c.frame.timeMs + 1e-7)
|| world.interactionLog[c.interactionIndex]?.timeMs <= c.frame.timeMs + 1e-7)
throw new Error('Pet checkpoint does not match its recording.');
const candidate = world.tape[c.bucketIndex];
const telemetry = candidate && c.frame.timeMs < candidate.simTimeMs + candidate.durationMs ? candidate : undefined;
if (JSON.stringify(c.frame.telemetry) !== JSON.stringify(telemetry))
throw new Error('Pet checkpoint telemetry does not match its clock.');
world.sim.restore(c.sim);
world.score.restore(c.score);
world.random.restore(c.random);
world.accumulator = c.accumulator;
world.tick = c.tick;
world.bucketIndex = c.bucketIndex;
world.interactionIndex = c.interactionIndex;
world.branchTick = c.branchTick;
world.behaviour = c.behaviour;
world.until = c.until;
world.targetX = c.targetX;
world.targetY = c.targetY;
world.x = c.x;
world.y = c.y;
world.flip = c.flip;
world.lit = c.lit;
world.lastActivity = c.lastActivity;
world.addressedAt = c.addressedAt ?? -Infinity;View on GitHub (pinned to 433685b202)