JuliusBrussee/caveman · error
${label}:${lineNo}: unexpected indent of ${indent} spaces
Error message
${label}:${lineNo}: unexpected indent of ${indent} spaces What it means
Thrown by the catalog parser when a non-empty, non-comment line's leading indent is neither 0, 2, nor 4 spaces. The parser's world model has exactly three levels (row dash line, row properties, block contents), so 1, 3, 6, 8 spaces, or any other width is structurally invalid — this includes YAML-legal odd indents and tabs expanded differently than the author assumed.
Source
Thrown at scripts/generate-agent-catalog.mjs:106
if (dash) {
if (row[blockKey] === undefined) row[blockKey] = [];
if (!Array.isArray(row[blockKey])) throw new Error(`${label}:${lineNo}: "${blockKey}" mixes map and sequence entries`);
row[blockKey].push(rest);
continue;
}
if (row[blockKey] === undefined) row[blockKey] = {};
if (Array.isArray(row[blockKey]) || typeof row[blockKey] !== "object") {
throw new Error(`${label}:${lineNo}: "${blockKey}" mixes map and sequence entries`);
}
const entry = splitKeyValue(rest, label, lineNo);
if (entry.value === undefined) throw new Error(`${label}:${lineNo}: nesting deeper than two levels is not supported`);
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`);View on GitHub (pinned to 27d5a3981a)
Solutions
- Re-indent the line named in the error to exactly 0 (row), 2 (row property), or 4 (block content) spaces.
- Configure the editor to insert spaces with a 2-space indent for this file and re-run the generator; fix each reported line as it surfaces.
- Ensure no tab characters are used for indentation anywhere in the file.
Example fix
# before - provider: anthropic model: claude-4 # 3 spaces # after - provider: anthropic model: claude-4 # 2 spaces
Defensive patterns
Strategy: validation
Validate before calling
function onlyIndent024(text) {
return text.split("\n").every((line) => {
if (line.trim() === "" || /^ *#/.test(line)) return true;
const indent = /^( *)/.exec(line)[1].length;
return [0, 2, 4].includes(indent) && !line.startsWith("\t");
});
} Try / catch
try {
parseCatalog(text);
} catch (err) {
if (/unexpected indent of \d+ spaces/.test(err.message)) {
// re-indent the named line to exactly 0, 2, or 4 spaces
} else throw err;
} Prevention
- Configure the editor: spaces only, 2-space indent, for catalog files.
- Enable an editorconfig/.editor_rule banning tabs in this file.
When it happens
Trigger: Indenting a line with 3 spaces between levels; using 6+ spaces for what was meant as a level-2 or level-4 line; mixing tabs and spaces so the counted indent falls outside {0,2,4}; a list item nested under a list item.
Common situations: Editor configured for a different indent width (e.g. 4-space default) applied inconsistently; copy-paste from a differently-indented file; hand-alignment that visually matches but measures differently.
Related errors
- ${label}:${lineNo}: unexpected sequence item at row level
- ${label}:${lineNo}: nested line without an open block
- ${label}:${lineNo}: expected a top-level "- provider: ..." r
- ${label}:${lineNo}: row must start with an inline "provider"
- ${label}:${lineNo}: indented line before any row
AI-assisted analysis of JuliusBrussee/caveman@27d5a3981a (2026-08-15).
Data as JSON: /api/errors/a066d6c180f21f22.
Report an issue: GitHub.