Hmbown/CodeWhale · error · Error

No pet segment was prepared.

Error message

No pet segment was prepared.

What it means

commitSegment() finalizes a recording segment previously created by prepareSegment(). The bridge stores the pending segment in this.segment; if commitSegment() is called without a prior prepareSegment(), or after the segment was already committed (which resets this.segment to undefined), there is nothing to commit and the bridge throws.

Solutions

  1. Call prepareSegment() and confirm it returned a recording JSON before calling commitSegment().
  2. Guard with needsSegment() before the prepare/commit pair and ensure it runs once per segment.
  3. Check whether a restoreCheckpoint/restoreRecording call reset the bridge state between prepare and commit.
  4. Deduplicate the commit callback so commitSegment() only runs once per segment.

Example fix

// before
bridge.prepareSegment();
bridge.commitSegment();
bridge.commitSegment(); // throws: segment already consumed
// after
if (bridge.needsSegment()) {
  bridge.prepareSegment();
  bridge.commitSegment(); // exactly once
}
Defensive patterns

Strategy: type-guard

Validate before calling

if (bridge.needsSegment()) {
  bridge.prepareSegment();
  pendingSegment = true;
}
// later, once:
if (pendingSegment) { bridge.commitSegment(); pendingSegment = false; }

Type guard

function canCommit(bridge, pendingSegment) {
  return pendingSegment === true && typeof bridge.prepareSegment === 'function';
}

Try / catch

try {
  bridge.commitSegment();
} catch (e) {
  if (e.message === 'No pet segment was prepared.') {
    // segment already committed or consumed by a restore; reset local flag
    pendingSegment = false;
  } else throw e;
}

Prevention

When it happens

Trigger: Calling commitSegment() when needsSegment()/prepareSegment() was never invoked, or calling commitSegment() twice in a row (the first call sets this.segment = undefined), or after restoreRecording()/restoreCheckpoint() which also clears this.segment.

Common situations: Race between the recording UI and a checkpoint restore that wiped the pending segment; double-commit on a completion callback firing twice; forgetting to call prepareSegment() after needsSegment() returned true.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@433685b202 (2026-09-15). Data as JSON: /api/errors/2566c5f24f278949. Report an issue: GitHub.

Appendix: source

Thrown at pet/ios/Resources/pet-native.js:66

    }
    /** Losing a producer invalidates outstanding coverage, never the creature. */
    disconnectEngine() { this.engine = new pet_engine_js_1.PetEngineTelemetry(); this.world.voices = []; }
    interact(kind, x, y) { this.world.interact(kind, x, y); }
    interactions() { return JSON.stringify(this.world.interactions); }
    accept(packet) { this.world.acceptTelemetry(JSON.parse(packet)); }
    acceptLiveTail(text) {
        const packet = this.liveTape.readTail(text);
        if (!packet)
            return false;
        this.world.acceptTelemetry(packet);
        return true;
    }
    resetLiveInput() { this.liveTape.reset(); return this.resumeEngine(); }
    recording(withCheckpoint = false) { return JSON.stringify(this.world.recording(withCheckpoint)); }
    needsSegment() { return this.world.needsSegment; }
    prepareSegment() { this.segment = this.world.prepareSegment(); return JSON.stringify(this.segment.recording); }
    commitSegment() { if (!this.segment)
        throw new Error('No pet segment was prepared.'); this.segment.commit(); this.segment = undefined; }
    checkpoint() { return JSON.stringify(this.world.checkpoint()); }
    recordingChunk(index, completed = false) { return this.world.recordingChunk(index, completed); }
    restoreCheckpoint(text) {
        if (text.length > 512 * 1024)
            throw new Error('Pet checkpoint exceeds its size limit.');
        this.restoreRecording(JSON.stringify({ ...this.world.recording(false), checkpoint: JSON.parse(text) }));
    }
    restoreRecording(text) {
        if (text.length > 8 * 1024 * 1024)
            throw new Error('Native habitat exceeds 8 MiB.');
        const points = this.world.sim.p.map(p => [p.hx, p.hy]);
        this.world = pet_world_js_1.PetWorld.fromRecording(points, JSON.parse(text));
        this.liveTape.reset();
        this.segment = undefined;
        this.engineTick = Math.round(this.world.frame.timeMs * 30 / 1000);
        this.engine = new pet_engine_js_1.PetEngineTelemetry();
    }
    /** Resume a live host at the first unrecorded bucket. Keep every accepted

View on GitHub (pinned to 433685b202)