JuliusBrussee/caveman · error

${label}:${lineNo}: indented line before any row

Error message

${label}:${lineNo}: indented line before any row

What it means

Thrown by the catalog parser when an indented line appears before any top-level "- provider: ..." row has been opened. Indented content can only belong to a row; with row still null there is nothing to attach it to, which almost always means the file's first row is malformed or missing its dash.

Source

Thrown at scripts/generate-agent-catalog.mjs:70

  for (let index = 0; index < lines.length; index++) {
    const line = lines[index].replace(/\s+$/, "");
    const lineNo = index + 1;
    if (line === "" || /^ *#/.test(line)) continue;
    const shape = /^( *)(- )?(.*)$/.exec(line);
    const indent = shape[1].length;
    const dash = shape[2] !== undefined;
    const rest = shape[3];
    if (indent === 0) {
      if (!dash) throw new Error(`${label}:${lineNo}: expected a top-level "- provider: ..." row`);
      row = {};
      rows.push(row);
      blockKey = null;
      const entry = splitKeyValue(rest, label, lineNo);
      if (entry.value === undefined) throw new Error(`${label}:${lineNo}: row must start with an inline "provider" value`);
      row[entry.key] = entry.value;
      continue;
    }
    if (row === null) throw new Error(`${label}:${lineNo}: indented line before any row`);
    if (indent === 2) {
      if (dash) throw new Error(`${label}:${lineNo}: unexpected sequence item at row level`);
      const entry = splitKeyValue(rest, label, lineNo);
      if (Object.prototype.hasOwnProperty.call(row, entry.key)) {
        throw new Error(`${label}:${lineNo}: duplicate key "${entry.key}"`);
      }
      if (entry.value === undefined) {
        blockKey = entry.key;
        row[entry.key] = undefined;
      } else {
        blockKey = null;
        row[entry.key] = entry.value;
      }
      continue;
    }
    if (indent === 4) {
      if (blockKey === null) throw new Error(`${label}:${lineNo}: nested line without an open block`);
      if (dash) {

View on GitHub (pinned to 27d5a3981a)

Solutions

  1. Go to the line named by label:lineNo and add the missing top-level "- provider: <value>" row above it.
  2. If the orphaned lines belong to a row that was deleted, remove them too or restore the row.
  3. Run the generator again to confirm no further structure errors follow.

Example fix

# before
  model: claude-4
  api: messages

# after
- provider: anthropic
  model: claude-4
  api: messages
Defensive patterns

Strategy: validation

Validate before calling

function firstContentLineIsRow(text) {
  const first = text.split("\n").find((l) => l.trim() !== "" && !/^ *#/.test(l));
  return first !== undefined && /^- provider: /.test(first.trimEnd());
}

Try / catch

try {
  parseCatalog(text);
} catch (err) {
  if (/indented line before any row/.test(err.message)) {
    // restore the "- provider: ..." header above the line named in the error
  } else throw err;
}

Prevention

When it happens

Trigger: The file starts with indented keys (e.g. the "- provider:" line was deleted or commented out, or the whole file was re-indented by an editor), or a comment marker was removed leaving orphaned child lines at the top.

Common situations: Accidentally deleting the first row's dash line while editing; a formatter re-indenting the file; resolving a merge conflict by keeping only the indented half.

Related errors


AI-assisted analysis of JuliusBrussee/caveman@27d5a3981a (2026-08-15). Data as JSON: /api/errors/c5ef506ad35d08bb. Report an issue: GitHub.