{"record":{"id":"103334aac7eae75f","repo":"Hmbown/CodeWhale","slug":"invalid-runtime-retention-horizon-pet-native","errorCode":null,"errorMessage":"Invalid Runtime retention horizon.","messagePattern":"Invalid Runtime retention horizon\\.","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"pet/ios/Resources/pet-native.js","lineNumber":2275,"sourceCode":"            this.bytes = total;\n            this.sizes.set(event, size);\n        }\n        for (const key of Object.keys(event))\n            if (!Object.hasOwn(safe, key))\n                delete event[key];\n        Object.assign(event, safe);\n    }\n    push(event) {\n        if (this.events.length >= this.maxEvents)\n            throw new Error(`Import exceeds the ${this.maxEvents.toLocaleString()} event limit.`);\n        this.measure(event);\n        pushEvent(this.events, event);\n    }\n    /** Keep unfinished lifetimes plus the recent window needed by the bucketer's\n     * 12-second recurrence measure. A completion may still arrive for any open item. */\n    prune(beforeWall) {\n        if (!Number.isFinite(beforeWall))\n            throw new Error('Invalid Runtime retention horizon.');\n        if (this.origin === undefined)\n            return;\n        const cutoff = beforeWall - this.origin;\n        let keep = 0;\n        for (const event of this.events) {\n            if (event.openEnded || Math.max(event.endTime, (0, model_js_1.errorOnsetOf)(event)) >= cutoff)\n                this.events[keep++] = event;\n            else {\n                this.bytes -= this.sizes.get(event) ?? 0;\n                this.sizes.delete(event);\n                if (this.open.get(event.id) === event)\n                    this.open.delete(event.id);\n            }\n        }\n        this.events.length = keep;\n    }\n    append(records) {\n        if (!records.length)","sourceCodeStart":2257,"sourceCodeEnd":2293,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/433685b2024e7bc4c99e1e2e326bcad39b4d9d65/pet/ios/Resources/pet-native.js#L2257-L2293","documentation":"Thrown by the Runtime retention tracker's prune(beforeWall) when the cutoff timestamp is not a finite number. prune() computes a wall-clock cutoff to decide which events to evict, so a non-finite argument (NaN, Infinity, undefined coerced) is treated as an invalid call rather than a best-effort prune. This is a fail-fast guard on the caller-supplied horizon.","triggerScenarios":"Calling runtime.prune() with a non-finite beforeWall: e.g. prune(Date.parse(badDateString)), prune(someUndefinedVariable), prune(Infinity), or passing a string instead of a number (pet/ios/Resources/pet-native.js:2275).","commonSituations":"Computing the horizon from an unparseable event timestamp (Date.parse returns NaN); passing an undefined variable after a failed lookup; mixing seconds/milliseconds units or strings with numbers; using Infinity intending 'keep everything'.","solutions":["Pass a finite numeric wall-clock timestamp (e.g. Date.now() or Date.parse of a validated ISO string).","Guard the call: only prune when Number.isFinite(beforeWall).","Fix the timestamp source that produced NaN (check date format/timezone).","If you want to keep everything, skip the prune call instead of passing Infinity."],"exampleFix":"// before\nruntime.prune(Date.parse(header.timestamp)); // NaN if unparseable\n// after\nconst t = Date.parse(header.timestamp);\nif (Number.isFinite(t)) runtime.prune(t);","handlingStrategy":"validation","validationCode":"const t = Date.parse(rawTimestamp);\nif (!Number.isFinite(t)) throw new Error(`Unparseable prune horizon: ${rawTimestamp}`);\nruntime.prune(t);","typeGuard":"function isFiniteTimestamp(v) {\n  return typeof v === 'number' && Number.isFinite(v);\n}","tryCatchPattern":"try {\n  runtime.prune(horizon);\n} catch (e) {\n  if (String(e.message).includes('retention horizon')) {\n    console.error(`prune() needs a finite wall-clock number, got ${horizon}`);\n  } else throw e;\n}","preventionTips":["Always pass numbers, never strings or undefined, to prune().","Validate Date.parse results (NaN check) before using them as horizons.","Never use Infinity to mean 'keep everything' — skip the call instead.","Standardize on milliseconds since epoch for all horizons."],"tags":["timestamp","validation","prune"],"backgroundTag":"invalid-argument-value","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"}