Hmbown/CodeWhale · error · Error

Pet segment checkpoints do not agree.

Error message

Pet segment checkpoints do not agree.

What it means

After restoring both the start checkpoint (`first`) and the checkpoint (or falling back), fromRecording cross-checks them: the restored world must be segmented, the checkpoint's tick must be at or after the start's tick, and if a mid-recording checkpoint exists its historyStart must equal the start's tick. Any disagreement means the start and checkpoint were not produced by the same segment and the combined replay would be incoherent.

Solutions

  1. Use start and checkpoint from the same recording/segment export — never mix them across files.
  2. Verify checkpoint.tick >= start.tick and checkpoint.historyStart === start.tick before restoring.
  3. Re-prepare the segment with prepareSegment() so both checkpoints are regenerated together.
  4. Re-record the segment if the originals came from divergent histories.

Example fix

// before
const r = { start: segA.start, checkpoint: segB.checkpoint, ... }; // mixed segments
const world = PetWorld.fromRecording(points, r); // throws
// after
const r = { ...segA, start: segA.start, checkpoint: segA.checkpoint };
const world = PetWorld.fromRecording(points, r);
Defensive patterns

Strategy: validation

Validate before calling

if (r.start && r.checkpoint) {
  if (r.checkpoint.tick < r.start.tick || r.checkpoint.historyStart !== r.start.tick)
    throw new Error('start/checkpoint belong to different segments');
}

Try / catch

try {
  world = PetWorld.fromRecording(points, r);
} catch (err) {
  if (err.message === 'Pet segment checkpoints do not agree.')
    console.error('Mixed segment data; re-prepare the segment.');
  else throw err;
}

Prevention

When it happens

Trigger: Calling `PetWorld.fromRecording(points, r)` with both r.start and r.checkpoint where: the restored world is not segmented, world.tick < first.tick (checkpoint earlier than start), or r.checkpoint.historyStart !== first.tick.

Common situations: Mixing start/checkpoint pairs from different segments or recordings; appending ticks to one segment but not the other; copying a checkpoint from an older archive into a newer segment file; a commit() race in prepareSegment after the world advanced.

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


AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22). Data as JSON: /api/errors/eec091ebbc0a318d. Report an issue: GitHub.

Appendix: source

Thrown at crates/tui/src/tui/pet_watch/pet-native.js:265

        if (!r || ![1, 2].includes(r.petReplayVersion) || !Array.isArray(r.tape) || !Array.isArray(r.interactions))
            throw new Error('Invalid pet recording.');
        const version = r.expressionVersion === undefined ? 1 : r.expressionVersion;
        if (![1, 2].includes(version))
            throw new Error('Unsupported pet expression version.');
        if (r.checkpoint !== undefined && !r.checkpoint || r.start !== undefined && !r.start)
            throw new Error('Invalid pet checkpoint.');
        for (const c of [r.start, r.checkpoint])
            if (c && (c.sim?.expressionVersion ?? 1) !== version)
                throw new Error('Pet expression version does not match its checkpoint.');
        if (r.petReplayVersion === 1 && (r.start || r.checkpoint && r.checkpoint.petCheckpointVersion !== 1))
            throw new Error('Invalid legacy pet recording.');
        if (r.petReplayVersion === 2 && (!r.start || r.start.petCheckpointVersion !== 2 || r.start.historyStart !== r.start.tick))
            throw new Error('The recording segment is missing its starting checkpoint.');
        const first = r.start && PetWorld.restore(points, r.tape, r.interactions, r.start);
        const world = r.checkpoint ? PetWorld.restore(points, r.tape, r.interactions, r.checkpoint) : first ?? new PetWorld(points, r.tape, r.interactions, version);
        if (first) {
            if (!world.segmented || world.tick < first.tick || r.checkpoint && r.checkpoint.historyStart !== first.tick)
                throw new Error('Pet segment checkpoints do not agree.');
            world.origin = first.checkpoint();
        }
        return world;
    }
    /** Retire only consumed input. The exact origin makes each archived segment
     * independently replayable; no particle, random stream or score is reset. */
    prepareSegment() {
        const dropTape = Math.max(0, this.bucketIndex), dropInputs = this.interactionIndex, previous = this.origin;
        const tape = this.tapeLog.slice(dropTape), interactions = this.interactionLog.slice(dropInputs);
        const points = this.sim.p.map(p => [p.hx, p.hy]);
        const c = this.checkpoint();
        c.petCheckpointVersion = 2;
        c.historyStart = this.tick;
        c.hasTelemetry = this.hasTelemetry;
        c.bucketIndex -= dropTape;
        c.interactionIndex = 0;
        c.history = new PetWorld(points, tape, interactions, this.sim.expressionVersion, true).historyDigest();
        const next = PetWorld.restore(points, tape, interactions, c);

View on GitHub (pinned to 73e0f67d83)