Hmbown/CodeWhale · error · Error

Invalid Runtime retention horizon.

Error message

Invalid Runtime retention horizon.

What it means

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.

Solutions

  1. Pass a finite numeric wall-clock timestamp (e.g. Date.now() or Date.parse of a validated ISO string).
  2. Guard the call: only prune when Number.isFinite(beforeWall).
  3. Fix the timestamp source that produced NaN (check date format/timezone).
  4. If you want to keep everything, skip the prune call instead of passing Infinity.

Example fix

// before
runtime.prune(Date.parse(header.timestamp)); // NaN if unparseable
// after
const t = Date.parse(header.timestamp);
if (Number.isFinite(t)) runtime.prune(t);
Defensive patterns

Strategy: validation

Validate before calling

const t = Date.parse(rawTimestamp);
if (!Number.isFinite(t)) throw new Error(`Unparseable prune horizon: ${rawTimestamp}`);
runtime.prune(t);

Type guard

function isFiniteTimestamp(v) {
  return typeof v === 'number' && Number.isFinite(v);
}

Try / catch

try {
  runtime.prune(horizon);
} catch (e) {
  if (String(e.message).includes('retention horizon')) {
    console.error(`prune() needs a finite wall-clock number, got ${horizon}`);
  } else throw e;
}

Prevention

When it happens

Trigger: 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).

Common situations: 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'.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@433685b202 (2026-09-15). Data as JSON: /api/errors/103334aac7eae75f. Report an issue: GitHub.

Appendix: source

Thrown at pet/ios/Resources/pet-native.js:2275

            this.bytes = total;
            this.sizes.set(event, size);
        }
        for (const key of Object.keys(event))
            if (!Object.hasOwn(safe, key))
                delete event[key];
        Object.assign(event, safe);
    }
    push(event) {
        if (this.events.length >= this.maxEvents)
            throw new Error(`Import exceeds the ${this.maxEvents.toLocaleString()} event limit.`);
        this.measure(event);
        pushEvent(this.events, event);
    }
    /** Keep unfinished lifetimes plus the recent window needed by the bucketer's
     * 12-second recurrence measure. A completion may still arrive for any open item. */
    prune(beforeWall) {
        if (!Number.isFinite(beforeWall))
            throw new Error('Invalid Runtime retention horizon.');
        if (this.origin === undefined)
            return;
        const cutoff = beforeWall - this.origin;
        let keep = 0;
        for (const event of this.events) {
            if (event.openEnded || Math.max(event.endTime, (0, model_js_1.errorOnsetOf)(event)) >= cutoff)
                this.events[keep++] = event;
            else {
                this.bytes -= this.sizes.get(event) ?? 0;
                this.sizes.delete(event);
                if (this.open.get(event.id) === event)
                    this.open.delete(event.id);
            }
        }
        this.events.length = keep;
    }
    append(records) {
        if (!records.length)

View on GitHub (pinned to 433685b202)