affaan-m/ECC · error
Canonical session snapshot requires
Error message
Canonical session snapshot requires ${fieldPath} to be a non-negative integer What it means
ensureInteger requires the field to be a non-negative integer (Number.isInteger(value) && value >= 0). This error means a numeric count/timestamp field was a float, NaN, negative, or a non-number. Canonical snapshots store counters strictly so comparisons like stale-threshold math (STALE_THRESHOLD_MS) behave predictably.
Solutions
- Find the field via ${fieldPath} and ensure it is Math.trunc'd and >= 0
- Guard timestamp math: check Number.isFinite before assigning (e.g. Number.isFinite(d.getTime()) ? d.getTime() : 0)
- Replace -1/NaN sentinels with a defined non-negative default
- Fix the producer adapter to clamp/round the value
Example fix
// before snapshot.session.lastUpdatedMs = new Date(raw).getTime(); // NaN if raw is invalid // after const t = new Date(raw).getTime(); snapshot.session.lastUpdatedMs = Number.isFinite(t) && t >= 0 ? Math.trunc(t) : 0;
Defensive patterns
Strategy: validation
Validate before calling
const okInt = (v) => Number.isInteger(v) && v >= 0;
Type guard
const isNonNegativeInteger = (v) => Number.isInteger(v) && v >= 0;
Try / catch
try { persistCanonicalSnapshot(s); } catch (e) { if (/non-negative integer/.test(e.message)) { /* clamp */ } else throw e; } Prevention
- Guard timestamp math with Number.isFinite
- Avoid negative sentinels
When it happens
Trigger: A snapshot field validated with ensureInteger holds -1, 1.5, NaN, undefined, or a numeric string, when passed through persistCanonicalSnapshot or a normalize* adapter.
Common situations: Computing timestamps with Date arithmetic that yields NaN (invalid date parse); sentinel values like -1 for 'unknown'; JSON numbers parsed from strings; floats from division when computing counts.
Understand the failure class
Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.
Related errors
- -32602
- artifact path must be a non-empty relative path
- assets must be a nonempty list
- built an invalid spec
- Canonical session snapshot must be an object
AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16).
Data as JSON: /api/errors/50e376018d9f4264.
Report an issue: GitHub.
Appendix: source
Thrown at scripts/lib/session-adapters/canonical-session.js:65
throw new Error(`Canonical session snapshot requires ${fieldPath} to be a string or null`);
}
}
function ensureBoolean(value, fieldPath) {
if (typeof value !== 'boolean') {
throw new Error(`Canonical session snapshot requires ${fieldPath} to be a boolean`);
}
}
function ensureArrayOfStrings(value, fieldPath) {
if (!Array.isArray(value) || value.some(item => typeof item !== 'string')) {
throw new Error(`Canonical session snapshot requires ${fieldPath} to be an array of strings`);
}
}
function ensureInteger(value, fieldPath) {
if (!Number.isInteger(value) || value < 0) {
throw new Error(`Canonical session snapshot requires ${fieldPath} to be a non-negative integer`);
}
}
const STALE_THRESHOLD_MS = 5 * 60 * 1000;
function parseUpdatedMs(updated) {
if (typeof updated !== 'string' || updated.length === 0) return null;
const ms = Date.parse(updated);
return Number.isNaN(ms) ? null : ms;
}
function deriveWorkerHealth(rawWorker) {
const state = (rawWorker.status && rawWorker.status.state) || 'unknown';
const completedStates = ['completed', 'succeeded', 'success', 'done'];
const failedStates = ['failed', 'error'];
if (failedStates.includes(state)) return 'degraded';
if (completedStates.includes(state)) return 'healthy';View on GitHub (pinned to 8321021c54)