{"record":{"id":"9f25dde43a220fdf","repo":"Hmbown/CodeWhale","slug":"invalid-version-1-pet-bucket","errorCode":null,"errorMessage":"Invalid version 1 pet bucket.","messagePattern":"Invalid version 1 pet bucket\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"crates/tui/src/tui/pet_watch/pet-native.js","lineNumber":1111,"sourceCode":"exports.encodePetJSONL = encodePetJSONL;\nexports.encodePetTSV = encodePetTSV;\nconst model_js_1 = require(\"./model.js\");\nconst signal_js_1 = require(\"./signal.js\");\nconst pet_sim_js_1 = require(\"./pet-sim.js\");\n/** One projection for imports, demos and recorded live snapshots. Times are ms.\n * These are aesthetic encodings of measured events, never model confidence. */\nexports.PET_BIN_MS = 400;\nfunction validatePetBucket(value) {\n    (0, pet_sim_js_1.validatePetState)(value);\n    const b = value;\n    if (!b || typeof b !== 'object' || b.version !== 1 || !Number.isSafeInteger(b.sequence) || b.sequence < 0 || b.sequence > pet_sim_js_1.PET_MAX_SECONDS * 2.5\n        || b.simTimeMs !== b.sequence * exports.PET_BIN_MS || b.durationMs !== exports.PET_BIN_MS\n        || !model_js_1.CATEGORIES.includes(b.channel) || typeof b.waiting !== 'boolean'\n        || !Array.isArray(b.agentIds) || b.agentIds.length > 250_000 || b.agentIds.some(id => typeof id !== 'string' || !id || id.length > 4096)\n        || !Number.isSafeInteger(b.errors) || b.errors < 0 || b.errors > 250_000\n        || !Array.isArray(b.onsets) || b.onsets.length !== 13 || b.onsets.some(n => !Number.isSafeInteger(n) || n < 0 || n > 250_000)\n        || !Array.isArray(b.activeMs) || b.activeMs.length !== 13 || b.activeMs.some(n => !Number.isFinite(n) || n < 0 || n > 100_000_000))\n        throw new Error('Invalid version 1 pet bucket.');\n}\nfunction decodePetJSONL(text) {\n    if (text.length > 64 * 1024 * 1024)\n        throw new Error('Pet tape exceeds 64 MiB.');\n    const rows = text.split(/\\r?\\n/).filter(line => line.trim()).map(line => JSON.parse(line));\n    if (rows.length > 216_000)\n        throw new Error('Pet tape exceeds 24 hours.');\n    return rows.map((row, i) => { validatePetBucket(row); if (row.sequence !== i)\n        throw new Error('Non-contiguous pet tape.'); return row; });\n}\n/** A live file must advance before its contents count as a new observation.\n * Existing bytes, duplicate samples and a restarted sequence establish a\n * baseline; they never replay an old onset or human request. Drivers supply a\n * bounded tail and reset this cursor after suspension or a new attachment. */\nclass PetLiveTape {\n    sequence;\n    reset() { this.sequence = undefined; }\n    readTail(text) {","sourceCodeStart":1093,"sourceCodeEnd":1129,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/src/tui/pet_watch/pet-native.js#L1093-L1129","documentation":"validatePetBucket checks each decoded version-1 pet bucket's shape: sequence-aligned simTimeMs and PET_BIN_MS durationMs, a channel present in CATEGORIES, boolean waiting, bounded agentIds (string, non-empty, <=4096 chars, <=250k), non-negative bounded errors count, and exactly 13-element onsets and activeMs arrays within bounds. A bucket failing any check throws 'Invalid version 1 pet bucket.'","triggerScenarios":"decodePetJSONL encountering a JSONL row whose bucket: has mismatched simTimeMs vs sequence*PET_BIN_MS, an unknown channel string, agentIds entries that are empty/oversized/non-string, negative errors, onsets/activeMs arrays of the wrong length (not 13) or containing out-of-range/NaN values.","commonSituations":"A pet tape file written by a different schema version (field renamed or missing, so the field is undefined and fails every typeof check); hand-assembled or corrupted rows; the v1 bucket written when PET_BIN_MS or the 13-channel layout differed from the current build.","solutions":["Identify the offending row index from the JSONL file and log the full row; compare each field against the v1 constraints above.","If the tape was written by another schema version, regenerate it with the current build instead of feeding it to the v1 validator.","Repair specific defects: set simTimeMs = sequence * PET_BIN_MS, durationMs = PET_BIN_MS, pad/truncate onsets and activeMs to 13 elements, and drop invalid agentIds entries.","Re-encode the tape after fixing, or discard the corrupt file and let the app rebuild it from the session log."],"exampleFix":"// before\nrows.map(JSON.parse).forEach(b => decodePetJSONL(b)); // b.onsets has 12 entries\n// after\nif (Array.isArray(b.onsets) && b.onsets.length === 13 &&\n    Array.isArray(b.activeMs) && b.activeMs.length === 13) {\n  decodePetJSONL(b);\n} else {\n  b.onsets = new Array(13).fill(0);\n  b.activeMs = new Array(13).fill(0);\n  decodePetJSONL(b);\n}","handlingStrategy":"validation","validationCode":"function bucketLooksValid(b, BIN_MS, CATEGORIES) {\n  return b && typeof b === 'object' &&\n    b.simTimeMs === b.sequence * BIN_MS && b.durationMs === BIN_MS &&\n    CATEGORIES.includes(b.channel) && typeof b.waiting === 'boolean' &&\n    Array.isArray(b.onsets) && b.onsets.length === 13 &&\n    Array.isArray(b.activeMs) && b.activeMs.length === 13 &&\n    Number.isSafeInteger(b.errors) && b.errors >= 0;\n}","typeGuard":"const isPetBucketV1 = (b, BIN_MS, CATEGORIES) => bucketLooksValid(b, BIN_MS, CATEGORIES);","tryCatchPattern":"try {\n  rows.forEach(validatePetBucket);\n} catch (e) {\n  if (e.message === 'Invalid version 1 pet bucket.') rebuildTapeFromSessionLog();\n  else throw e;\n}","preventionTips":["Write tapes only through the current encoder so field shapes always match the v1 validator.","Keep onsets/activeMs exactly 13 elements at write time.","Skip/drop rows with undefined fields instead of letting them reach the validator; log them for repair."],"tags":["validation","schema","persistence"],"backgroundTag":"schema-validation-failed","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-22T16:17:23.217Z"}