{"record":{"id":"33f219834a4b8518","repo":"Hmbown/CodeWhale","slug":"pet-bucket-exceeds-the-recording-segment-byte-limit","errorCode":null,"errorMessage":"Pet bucket exceeds the recording segment byte limit.","messagePattern":"Pet bucket exceeds the recording segment byte limit\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"pet/scripts/lib/pet-recorder.mjs","lineNumber":111,"sourceCode":"      }\n    }\n    expectedMtime ??= (await output.stat({ bigint: true })).mtimeNs;\n  } catch (error) { try { await output?.close(); } finally { lock.close(); } throw error; }\n  return {\n    async append(bucket) {\n      if (!output || busy) throw new Error('Pet recorder is closed or already writing.');\n      validatePetBucket(bucket);\n      busy = true;\n      try {\n        await lock.check();\n        const held = await output.stat({ bigint: true }), current = await lstat(path, { bigint: true });\n        if (!current.isFile() || held.dev !== current.dev || held.ino !== current.ino || held.size !== BigInt(bytes) || held.mtimeNs !== expectedMtime)\n          throw new Error('The live pet recording was changed or replaced externally; existing files were preserved.');\n        const encode = seq => encodePetJSONL([{ ...bucket, sequence: seq, simTimeMs: seq * PET_BIN_MS }]);\n        let row = encode(sequence), size = Buffer.byteLength(row);\n        if (restart || sequence >= maxBuckets || bytes + size > maxBytes) {\n          row = encode(0); size = Buffer.byteLength(row);\n          if (size > maxBytes) throw new Error('Pet bucket exceeds the recording segment byte limit.');\n          const temporary = resolve(dirname(path), `.${basename(path)}.next-${randomUUID()}`);\n          const archive = `${path}.segment-${String(segment + 1).padStart(6, '0')}.jsonl`;\n          let next, installed = false, created = false;\n          try {\n            next = await open(temporary, 'wx', 0o600); created = true;\n            await next.writeFile(row); await next.sync();\n            const nextIdentity = await next.stat({ bigint: true });\n            await next.close(); next = undefined;\n            await output.sync();\n            // link is exclusive: a collision never replaces someone else's\n            // archive. Persist this name before replacing the live pathname.\n            await link(path, archive); await syncDirectory(dirname(path));\n            // Windows can reject replacement while either writer handle is\n            // open. Both files are synced and the old file is archived first.\n            await output.close(); output = undefined;\n            for (let attempt = 0; ; attempt++) {\n              await lock.check();\n              const destination = await lstat(path, { bigint: true });","sourceCodeStart":93,"sourceCodeEnd":129,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/433685b2024e7bc4c99e1e2e326bcad39b4d9d65/pet/scripts/lib/pet-recorder.mjs#L93-L129","documentation":"During rotation the recorder encodes the bucket as the first row of a new segment (sequence 0); if that single encoded row already exceeds the configured max segment byte size, no segment could ever hold it, so it throws before creating any files.","triggerScenarios":"Appending a pet bucket whose JSONL encoding (all fields plus sequence and simTimeMs) is larger than maxBytes; a bucket carrying a very large string field or nested payload that inflates the row.","commonSituations":"Downsizing maxBytes below the size of already-produced buckets; a bug producing oversized bucket payloads (huge labels/notes); misconfigured segment limit after changing bucket schema.","solutions":["Inspect the bucket payload and shrink oversized fields before appending.","Increase the recorder's maxBytes segment limit to exceed one encoded row.","Fix the producer that emits abnormally large buckets (cap string lengths at the source).","If this is recurring, add a payload-size check in the producer before calling append()."],"exampleFix":"// before\ncreatePetRecorder(path, { maxBytes: 64 });\n// after\ncreatePetRecorder(path, { maxBytes: 1024 * 1024 });","handlingStrategy":"validation","validationCode":"const encoded = JSON.stringify(bucket) + '\\n';\nif (Buffer.byteLength(encoded) > maxBytes) throw new Error('bucket row exceeds segment limit; shrink payload or raise maxBytes');","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep maxBytes comfortably larger than your largest possible bucket row","Cap string fields in pet buckets at the producer","Re-check limits after changing the bucket schema","Compute the worst-case encoded row size when configuring maxBytes"],"tags":["validation","size-limit","configuration"],"backgroundTag":"payload-too-large","analyzedSha":"433685b2024e7bc4c99e1e2e326bcad39b4d9d65","analyzedAt":"2026-09-15T12:24:24.634Z","contentChangedAt":"2026-09-15T12:24:24.634Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}