ruvnet/ruflo · error · Error
unsupported calibrator schema v=${j?.v}
Error message
unsupported calibrator schema v=${j?.v} What it means
Thrown by IsotonicCalibrator.fromJSON(j) when j is null/undefined OR j.v !== 1. The calibrator file format is versioned with a single schema version (v:1, holding a buckets array); any other version, or a payload missing the v field, is rejected. This guards against silently applying a calibrator fit for a different schema — which would produce garbage predictedQuality values in the router.
Source
Thrown at v3/@claude-flow/cli/src/ruvector/router-calibrator.ts:128
// Linear interpolation between two adjacent bucket midpoints. Could be
// binary-searched, but n is typically <30 after PAV so linear is fine.
for (let i = 0; i < n - 1; i++) {
if (x >= mids[i] && x <= mids[i + 1]) {
const t = (x - mids[i]) / (mids[i + 1] - mids[i]);
return this.buckets[i].calibrated * (1 - t) + this.buckets[i + 1].calibrated * t;
}
}
return x; // unreachable given the bounds above
}
/** Pure-JSON serialization — calibrator JSON is small (typically <2kB). */
toJSON(): CalibratorJSON {
return { v: 1, buckets: this.buckets };
}
static fromJSON(j: CalibratorJSON): IsotonicCalibrator {
if (!j || j.v !== 1) throw new Error(`unsupported calibrator schema v=${j?.v}`);
return new IsotonicCalibrator(j.buckets);
}
/** Diagnostic — number of distinct calibration points after PAV. */
get bucketCount(): number {
return this.buckets.length;
}
/** Diagnostic — return a copy of the bucket array (read-only view). */
inspect(): CalibratorBucket[] {
return this.buckets.map(b => ({ ...b }));
}
}
View on GitHub (pinned to 6b01dc5a68)
Solutions
- Inspect the file at cfg.calibratorPath — it must contain {"v":1,"buckets":[...]}.
- Regenerate the calibrator with IsotonicCalibrator.fit(...).toJSON() on the current version and overwrite the file.
- If the file is from an incompatible version, delete it and disable calibration (CLAUDE_FLOW_ROUTER_CALIBRATE=0) until a matching one is produced.
- Guard fromJSON calls so a bad calibrator disables calibration rather than crashing router init — loadCal in neural-router already does this (catch returns null).
Example fix
// before — direct fromJSON on untrusted payload
const cal = IsotonicCalibrator.fromJSON(JSON.parse(raw));
// after — schema-check first, fall back to no-calibration
let cal = null;
try {
const j = JSON.parse(raw);
if (j && j.v === 1) cal = IsotonicCalibrator.fromJSON(j);
} catch { /* leave cal null */ }
const router = cal ? wrapWithCalibrator(r, cal) : r; Defensive patterns
Strategy: validation
Validate before calling
import { IsotonicCalibrator } from './router-calibrator';
function loadCalibratorSafe(path: string) {
try {
const j = JSON.parse(readFileSync(path, 'utf8'));
if (!j || j.v !== 1) return null; // wrong schema → disable calibration
return IsotonicCalibrator.fromJSON(j);
} catch {
return null;
}
} Type guard
function isCalibratorJSONv1(j: unknown): j is { v: 1; buckets: unknown[] } {
return !!j && typeof j === 'object' && (j as any).v === 1 && Array.isArray((j as any).buckets);
} Try / catch
let calibrator = null;
try {
calibrator = IsotonicCalibrator.fromJSON(parsed);
} catch (e) {
if (/unsupported calibrator schema/.test(String(e))) {
// Disable calibration rather than crashing router init.
console.warn('calibrator schema mismatch — running uncalibrated');
} else throw e;
} Prevention
- Always set { v: 1 } via IsotonicCalibrator.toJSON() — don't hand-write calibrator JSON.
- Validate the schema (v === 1 && Array.isArray(buckets)) before calling fromJSON.
- When upgrading @claude-flow/cli, regenerate calibrator artifacts to match the runtime version.
- Load calibrators through the neural-router's loadCal helper, which already swallows errors to null.
When it happens
Trigger: Loading a calibrator JSON written by a future version (v:2); loading a partial/empty file ({}, null); loading a file that's actually a different JSON (e.g. the KRR artifact) by mistake; the file was hand-edited and the v field was removed; JSON.parse on an empty file returns null and that's passed in.
Common situations: Cross-version install: calibrator was generated by a newer @claude-flow/cli and loaded by an older one (or vice versa); a path misconfiguration points calibratorPath at the wrong JSON; CI copied a stale calibrator from an old release; the calibrator file got truncated to empty during a write.
Related errors
- failed to load unified KRR
- RVFA header failed validation
- pod-template at ${path}: field "${key}" must be a non-empty
- pod-template at ${path}: field "${key}" must be a finite num
- pod-template at ${path}: field "${key}" must be a boolean
AI-assisted analysis of ruvnet/ruflo@6b01dc5a68 (2026-08-12).
Data as JSON: /api/errors/38609a908a2e3f7d.
Report an issue: GitHub.