JuliusBrussee/caveman · error
${label}: ${field} must be a finite non-negative number
Error message
${label}: ${field} must be a finite non-negative number What it means
Thrown by rate() in scripts/generate-agent-catalog.mjs when a pricing field inside a selected (global, USD) row is present but is not a finite non-negative number: negative values, NaN, Infinity, or non-number scalars (booleans, strings) all fail. Null and undefined are legal (they mean 'not offered' and cause the row to be skipped or default to 0 for cache rates), which is why only bad non-null values throw.
Source
Thrown at scripts/generate-agent-catalog.mjs:208
});
}
selected.sort((left, right) => (left.key < right.key ? -1 : left.key > right.key ? 1 : 0));
const skipped = [...skippedByKey.entries()]
.map(([key, entry]) => {
const reasons = [...entry.reasons].sort();
if (entry.regions.length > 0) {
reasons.unshift(`priced per region only (${[...entry.regions].sort().join(", ")})`);
}
return { key, reason: reasons.join("; ") };
})
.sort((left, right) => (left.key < right.key ? -1 : left.key > right.key ? 1 : 0));
return { selected, skipped };
}
function rate(value, field, label) {
if (value === undefined || value === null) return null;
if (typeof value !== "number" || !Number.isFinite(value) || value < 0) {
throw new Error(`${label}: ${field} must be a finite non-negative number`);
}
return value;
}
function number(value) {
const text = String(value);
if (!/^(0|[1-9][0-9]*)(\.[0-9]+)?(e[+-]?[0-9]+)?$/.test(text)) {
throw new Error(`cannot render ${text} as a stable numeric literal`);
}
return text;
}
/** Renders the full public/agent/src/catalog.ts module text. */
export function renderCatalogModule(catalogBytes, label = CATALOG_LABEL) {
const digest = createHash("sha256").update(catalogBytes).digest("hex");
const { selected, skipped } = selectRows(parseCatalogYaml(catalogBytes.toString("utf8"), label), label);
if (selected.length === 0) throw new Error(`${label}: no priced region-agnostic rows found`);
const entries = selected.map(({ key, price }) => [View on GitHub (pinned to 27d5a3981a)
Solutions
- Fix the named field to a plain non-negative number (e.g. 0.25); use null (not 0) when the rate genuinely does not exist — the script deliberately maps null cache rates to 0 only for cache fields.
- Remove quotes around numeric values in the YAML so they parse as numbers, not strings.
- Re-run the generator to confirm the row validates.
Example fix
# before
pricing:
input_per_million: "1.5"
output_per_million: -6
# after
pricing:
input_per_million: 1.5
output_per_million: 6 Defensive patterns
Strategy: type-guard
Type guard
function isValidRate(v) {
return v === undefined || v === null || (typeof v === "number" && Number.isFinite(v) && v >= 0);
} Prevention
- Write prices as unquoted numeric literals; strings and booleans always fail.
- Use null for 'rate not offered', never 0 or a negative placeholder.
When it happens
Trigger: A pricing field like `input_per_million: -1` (negative), `input_per_million: true`, `input_per_million: "3"` (quoted string), or a value that parsed to NaN. The field name in the message identifies exactly which rate on which provider/model is bad.
Common situations: Recording a discount as a negative number; quoting prices as strings when pasting from a spreadsheet; a `true`/`false` value left from experimentation; null-vs-0 confusion for cache rates.
Related errors
- ${label}:${lineNo}: "${text}" is not a finite number
- ${label}: ${key} has no pricing block
- %s: provider, model, and region are required
- %s %s/%s: unsupported currency %q
- %s %s/%s: invalid pricing
AI-assisted analysis of JuliusBrussee/caveman@27d5a3981a (2026-08-15).
Data as JSON: /api/errors/58315ec1cfeb97af.
Report an issue: GitHub.