{"record":{"id":"7a3f715fc5a57536","repo":"Hmbown/CodeWhale","slug":"world-requires-contiguous-version-1-pet-buckets-7a3f71","errorCode":null,"errorMessage":"World requires contiguous version 1 pet buckets.","messagePattern":"World requires contiguous version 1 pet buckets\\.","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"pet/src/core/pet-world.ts","lineNumber":100,"sourceCode":"  private hasTelemetry = false;\n  get startTimeMs(): number { return this.origin?.frame.timeMs ?? 0; }\n  get endTimeMs(): number { return Math.max(this.frame.timeMs, (this.tapeLog.at(-1)?.simTimeMs ?? 0) + 400); }\n  get needsSegment(): boolean {\n    return !this.segmented && this.tapeLog.length < 1024 && this.interactionLog.length < 4096\n      || this.bucketIndex >= 1024 || this.interactionIndex >= 4096;\n  }\n\n  constructor(points: [number, number][], tape: readonly PetBucket[] = [], interactions: readonly PetInteraction[] = [], expressionVersion: 1 | 2 = 2, segmented = false) {\n    if (tape.length > 216_000 || interactions.length > 100_000) throw new Error('Pet recording exceeds its input limit.');\n    this.sim = new PetSim(points, 0xC0FFEE, expressionVersion);\n    this.segmented = segmented; this.hasTelemetry = tape.length > 0;\n    this.tapeLog = structuredClone([...tape]);\n    this.interactionLog = structuredClone([...interactions]);\n    for (let i = 0; i < this.tape.length; i++) {\n      const b = this.tape[i];\n      validatePetBucket(b);\n      if (segmented ? i > 0 && b.sequence <= this.tape[i - 1].sequence : b.sequence !== i)\n        throw new Error('World requires contiguous version 1 pet buckets.');\n    }\n    for (let i = 0; i < this.interactionLog.length; i++) {\n      const e = this.interactionLog[i];\n      if (!Number.isFinite(e.timeMs) || e.timeMs < 0 || i > 0 && e.timeMs < this.interactionLog[i - 1].timeMs\n        || !['attention', 'food'].includes(e.kind) || !Number.isFinite(e.x) || !Number.isFinite(e.y)\n        || Math.abs(e.x) > 1 || Math.abs(e.y) > 1) throw new Error('Invalid pet interaction.');\n    }\n    this.hashTape(0);\n    this.frame = this.makeFrame(0);\n    this.voices = this.score.voices(this.frame);\n    if (segmented) this.origin = this.checkpoint();\n  }\n\n  checkpoint(): PetWorldCheckpoint {\n    return structuredClone({ petCheckpointVersion: this.segmented ? 2 : 1,\n      ...(this.segmented ? { historyStart: (this.origin?.tick ?? this.tick), hasTelemetry: this.hasTelemetry } : {}), history: this.historyDigest(),\n      sim: this.sim.checkpoint(), score: this.score.checkpoint(), accumulator: this.accumulator,\n      tick: this.tick, bucketIndex: this.bucketIndex, interactionIndex: this.interactionIndex, branchTick: this.branchTick,","sourceCodeStart":82,"sourceCodeEnd":118,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/433685b2024e7bc4c99e1e2e326bcad39b4d9d65/pet/src/core/pet-world.ts#L82-L118","documentation":"PetWorld validates every bucket with validatePetBucket and requires sequences to line up: unsegmented recordings must have b.sequence === i exactly; segmented recordings must be strictly increasing. Violations throw this error.","triggerScenarios":"Passing a tape with gaps or duplicate sequences to an unsegmented PetWorld; passing a non-monotonic (decreasing or repeating) sequence to a segmented recording; buckets failing validatePetBucket (e.g. wrong version or shape).","commonSituations":"Manually splicing tapes together; restoring from a partial export that skipped buckets; mixing segmented and unsegmented loading modes.","solutions":["Ensure bucket sequences are 0,1,2,... for unsegmented recordings.","For segmented recordings, ensure sequences are strictly increasing with no repeats.","Rebuild the tape via compilePetTelemetry instead of hand-constructing buckets.","Verify each bucket passes validatePetBucket (version 1, valid shape)."],"exampleFix":"// before\nnew PetWorld(points, tape.filter(b => keepCondition(b)));\n// after\nconst filtered = tape.filter(b => keepCondition(b))\n  .map((b, i) => ({ ...b, sequence: i }));\nnew PetWorld(points, filtered);","handlingStrategy":"validation","validationCode":"function isContiguous(tape) { return tape.every((b, i) => b.sequence === i); }\nif (!isContiguous(tape)) tape = tape.map((b, i) => ({ ...b, sequence: i }));","typeGuard":"const isBucketV1 = (b) => !!b && b.version === 1 && Number.isSafeInteger(b.sequence);","tryCatchPattern":"try { new PetWorld(points, tape, interactions); } catch (e) { if (e.message.includes('contiguous')) resequenceAndRetry(tape); }","preventionTips":["Only build tapes via compilePetTelemetry.","Never hand-splice bucket arrays without renumbering sequences."],"tags":["validation","data-integrity"],"backgroundTag":"schema-validation-failed","analyzedSha":"433685b2024e7bc4c99e1e2e326bcad39b4d9d65","analyzedAt":"2026-09-15T12:24:24.634Z","contentChangedAt":"2026-09-15T12:24:24.634Z","schemaVersion":2},"datasetVersion":"2026-09-22T11:17:16.035Z"}