JuliusBrussee/caveman · error
${label}:${lineNo}: empty value
Error message
${label}:${lineNo}: empty value What it means
Thrown by scalar() in scripts/generate-agent-catalog.mjs when a `key:` line has a trailing space, so the regex captures an empty value string instead of no value. The parser distinguishes `key:` (value undefined, opens a nested block) from `key: ` (empty value after the space), and an empty value is meaningless for pricing data, so it is rejected rather than silently treated as null or empty string.
Source
Thrown at scripts/generate-agent-catalog.mjs:118
if (Object.prototype.hasOwnProperty.call(row[blockKey], entry.key)) {
throw new Error(`${label}:${lineNo}: duplicate key "${blockKey}.${entry.key}"`);
}
row[blockKey][entry.key] = entry.value;
continue;
}
throw new Error(`${label}:${lineNo}: unexpected indent of ${indent} spaces`);
}
return rows;
}
function splitKeyValue(text, label, lineNo) {
const match = /^([A-Za-z_][A-Za-z0-9_]*):(?: (.*))?$/.exec(text);
if (match === null) throw new Error(`${label}:${lineNo}: cannot read "${text}" as a "key: value" pair`);
return { key: match[1], value: match[2] === undefined ? undefined : scalar(match[2], label, lineNo) };
}
function scalar(text, label, lineNo) {
if (text === "") throw new Error(`${label}:${lineNo}: empty value`);
if (text === "null") return null;
if (text === "true") return true;
if (text === "false") return false;
if (/^-?(0|[1-9][0-9]*)(\.[0-9]+)?([eE][+-]?[0-9]+)?$/.test(text)) {
const value = Number(text);
if (!Number.isFinite(value)) throw new Error(`${label}:${lineNo}: "${text}" is not a finite number`);
return value;
}
return text;
}
/** Selects the priced, region-agnostic, USD rows the agent catalog can honestly carry. */
export function selectRows(rows, label = CATALOG_LABEL) {
const selected = [];
const skippedByKey = new Map();
const seen = new Set();
const record = (key) => {
let entry = skippedByKey.get(key);View on GitHub (pinned to 27d5a3981a)
Solutions
- Go to the line named in the message and either supply a real value (`model: gpt-4o`) or remove the trailing space so the line is exactly `model:` when you intend a nested block.
- Check nearby lines for the same trailing-space pattern (e.g. `grep -n ': *$' current.yaml`).
- Re-run the generator to verify the catalog parses.
Example fix
# before output_per_million: # after output_per_million: 15
Defensive patterns
Strategy: validation
Validate before calling
// Reject `key: ` lines with an empty captured value before generating.
const bad = text.split("\n").flatMap((line, i) => {
const m = /^([A-Za-z_][A-Za-z0-9_]*): (.*)$/.exec(line.replace(/\s+$/, ""));
return m && m[2] === "" ? [i + 1] : [];
}); Try / catch
catch (error) {
if (/empty value$/.test(error.message)) { const [, lineNo] = error.message.match(/:(\d+):/); fixEmptyValue(lineNo); }
else throw error;
} Prevention
- Configure your editor to trim trailing whitespace on save.
- Never leave `key: ` skeletons in the catalog; write the value or delete the line.
When it happens
Trigger: A row line written as `model: ` or `input_per_million: ` — colon, one space, end of line (trailing whitespace is stripped only at end-of-line, so the captured group is the empty string). splitKeyValue then calls scalar("") which raises this error with the file label and line number.
Common situations: Editors or linters that keep a trailing space after the colon; deleting a value while leaving its `key: ` skeleton during catalog editing; copy-pasting from a source that pads values.
Related errors
- ${label}:${lineNo}: cannot read "${text}" as a "key: value"
- ${label}:${lineNo}: expected a top-level "- provider: ..." r
- ${label}:${lineNo}: row must start with an inline "provider"
- ${label}:${lineNo}: indented line before any row
- ${label}:${lineNo}: "${text}" is not a finite number
AI-assisted analysis of JuliusBrussee/caveman@27d5a3981a (2026-08-15).
Data as JSON: /api/errors/7f49b952eddb75dd.
Report an issue: GitHub.