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 with prepareSegment(). If prepareSegment() was never called — or the segment was already committed, which clears this.segment — the internal this.segment is undefined and the call throws. It is an ordering/state guard, not a data problem.
Solutions
- Gate the commit on needsSegment()/prepareSegment(): call prepareSegment() first, then commitSegment() exactly once
- Track a boolean 'segmentOpen' in the caller and skip the second commit
- Re-create the segment (prepareSegment) if the world was restored between prepare and commit
- Catch the error and treat it as a no-op if your commit path is idempotent by design
Example fix
// before
pet.commitSegment();
// after
if (pet.needsSegment() === false) { pet.prepareSegment(); }
pet.commitSegment(); Defensive patterns
Strategy: try-catch
Validate before calling
if (!segmentOpen) { pet.prepareSegment(); segmentOpen = true; } Try / catch
try {
pet.commitSegment();
segmentOpen = false;
} catch (err) {
if (err.message === 'No pet segment was prepared.') { segmentOpen = false; }
else throw err;
} Prevention
- Always pair prepareSegment()/commitSegment() in one function
- Track segment-open state explicitly in the caller
- Never interleave restore calls between prepare and commit
When it happens
Trigger: Calling pet.commitSegment() without a prior pet.prepareSegment(); calling commitSegment() twice in a row (the first commit sets this.segment = undefined); calling commitSegment() after restoreRecording/restoreCheckpoint, which reset this.segment to undefined.
Common situations: Double-flushing a recording pipeline; racing timers that both call commitSegment; restarting/restoring a session between prepare and commit.
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
- No pet segment was prepared.
- Only a live recording can resume observation.
- This Runtime already owns a task execution manager
- A cancelled Operation cannot be edited.
- Agent not found
AI-assisted analysis of Hmbown/CodeWhale@433685b202 (2026-09-15).
Data as JSON: /api/errors/58a8c6c1f3215e89.
Report an issue: GitHub.
Appendix: source
Thrown at pet/src/core/pet-native.ts:54
}
return JSON.stringify({ ...frame, digest: digest(sim), style: sim.frame, activity: this.engine.activity(frame.timeMs),
points: sim.p.map(p => [p.x, p.y]),
still: { points: this.stillProjection.points, style: this.stillProjection.style, state } });
}
/** Losing a producer invalidates outstanding coverage, never the creature. */
disconnectEngine(): void { this.engine = new PetEngineTelemetry(); this.world.voices = []; }
interact(kind: PetInteraction['kind'], x: number, y: number): void { this.world.interact(kind, x, y); }
interactions(): string { return JSON.stringify(this.world.interactions); }
accept(packet: string): void { this.world.acceptTelemetry(JSON.parse(packet)); }
acceptLiveTail(text: string): boolean {
const packet = this.liveTape.readTail(text); if (!packet) return false;
this.world.acceptTelemetry(packet); return true;
}
resetLiveInput(): number { this.liveTape.reset(); return this.resumeEngine(); }
recording(withCheckpoint = false): string { return JSON.stringify(this.world.recording(withCheckpoint)); }
needsSegment(): boolean { return this.world.needsSegment; }
prepareSegment(): string { this.segment = this.world.prepareSegment(); return JSON.stringify(this.segment.recording); }
commitSegment(): void { if (!this.segment) throw new Error('No pet segment was prepared.'); this.segment.commit(); this.segment = undefined; }
checkpoint(): string { return JSON.stringify(this.world.checkpoint()); }
recordingChunk(index: number, completed = false): string | null { return this.world.recordingChunk(index, completed); }
restoreCheckpoint(text: string): void {
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: string): void {
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] as [number, number]);
this.world = 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 PetEngineTelemetry();
}
/** Resume a live host at the first unrecorded bucket. Keep every accepted
* interval, but never present its last observed frame as current evidence. */
resumeEngine(): number {
this.world.resumeObservation();
this.engineTick = Math.round(this.world.frame.timeMs * 30 / 1000);View on GitHub (pinned to 433685b202)