{"record":{"id":"110ac054209bb671","repo":"Hmbown/CodeWhale","slug":"pet-tape-exceeds-24-hours-native","errorCode":null,"errorMessage":"Pet tape exceeds 24 hours.","messagePattern":"Pet tape exceeds 24 hours\\.","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"pet/ios/Resources/pet-native.js","lineNumber":1118,"sourceCode":"exports.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) {\n        if (!text) {\n            this.reset();\n            return;\n        }\n        if (text.length > 262_144) {\n            this.reset();\n            throw new Error('Live pet input exceeds its tail limit.');","sourceCodeStart":1100,"sourceCodeEnd":1136,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/433685b2024e7bc4c99e1e2e326bcad39b4d9d65/pet/ios/Resources/pet-native.js#L1100-L1136","documentation":"A pet tape may contain at most 216,000 rows — one bucket per PET_BIN_MS covering 24 hours. decodePetJSONL throws this error when the parsed row count exceeds that cap, preventing multi-day tapes from being replayed as if they were a single day.","triggerScenarios":"decodePetJSONL given text with more than 216,000 non-empty JSONL lines — e.g. a tape spanning multiple days, duplicated rows from double-appending, or a producer using a smaller bin duration than PET_BIN_MS (yielding more rows per day).","commonSituations":"Tape files accumulated across several days without rotation; a producer bug emitting sub-bin samples as separate rows; concatenated tapes from multiple devices.","solutions":["Trim the tape to the most recent 216,000 rows before decoding.","Fix the producer to emit exactly one row per PET_BIN_MS interval.","Deduplicate or rotate the tape at the source.","Only decode the trailing 24-hour window you care about."],"exampleFix":"// before\nconst rows = decodePetJSONL(entireWeekText);\n// after\nconst lines = entireWeekText.trim().split('\\n').slice(-216000);\nconst rows = decodePetJSONL(lines.join('\\n'));","handlingStrategy":"validation","validationCode":"const lineCount = text.split('\\n').filter(l => l.trim()).length;\nif (lineCount > 216000) text = text.split('\\n').slice(-216000).join('\\n');","typeGuard":"const fitsIn24h = (text) => text.split('\\n').filter(l => l.trim()).length <= 216000;","tryCatchPattern":"try { rows = decodePetJSONL(text); }\ncatch (e) { if (e.message === 'Pet tape exceeds 24 hours.') { rows = decodePetJSONL(lastDay(text)); } else throw e; }","preventionTips":["Emit exactly one bucket per PET_BIN_MS interval.","Trim to the trailing 24h window before loading.","Deduplicate producer rows instead of appending duplicates.","Monitor tape row counts in telemetry."],"tags":["limits","telemetry","duration"],"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-22T16:17:23.217Z"}