{"record":{"id":"79317d9c6a0aea8d","repo":"JuliusBrussee/caveman","slug":"label-lineno-expected-a-top-level-provid","errorCode":null,"errorMessage":"${label}:${lineNo}: expected a top-level \"- provider: ...\" row","messagePattern":"(.+?):(.+?): expected a top-level \"- provider: \\.\\.\\.\" row","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"scripts/generate-agent-catalog.mjs","lineNumber":61,"sourceCode":"const REGION_AGNOSTIC = \"global\";\nconst REQUIRED_CURRENCY = \"USD\";\n\n/** Parses the flat `- key: value` catalog sequence. Throws on any other shape. */\nexport function parseCatalogYaml(text, label = CATALOG_LABEL) {\n  const rows = [];\n  let row = null;\n  let blockKey = null;\n  const lines = text.split(\"\\n\");\n  for (let index = 0; index < lines.length; index++) {\n    const line = lines[index].replace(/\\s+$/, \"\");\n    const lineNo = index + 1;\n    if (line === \"\" || /^ *#/.test(line)) continue;\n    const shape = /^( *)(- )?(.*)$/.exec(line);\n    const indent = shape[1].length;\n    const dash = shape[2] !== undefined;\n    const rest = shape[3];\n    if (indent === 0) {\n      if (!dash) throw new Error(`${label}:${lineNo}: expected a top-level \"- provider: ...\" row`);\n      row = {};\n      rows.push(row);\n      blockKey = null;\n      const entry = splitKeyValue(rest, label, lineNo);\n      if (entry.value === undefined) throw new Error(`${label}:${lineNo}: row must start with an inline \"provider\" value`);\n      row[entry.key] = entry.value;\n      continue;\n    }\n    if (row === null) throw new Error(`${label}:${lineNo}: indented line before any row`);\n    if (indent === 2) {\n      if (dash) throw new Error(`${label}:${lineNo}: unexpected sequence item at row level`);\n      const entry = splitKeyValue(rest, label, lineNo);\n      if (Object.prototype.hasOwnProperty.call(row, entry.key)) {\n        throw new Error(`${label}:${lineNo}: duplicate key \"${entry.key}\"`);\n      }\n      if (entry.value === undefined) {\n        blockKey = entry.key;\n        row[entry.key] = undefined;","sourceCodeStart":43,"sourceCodeEnd":79,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/27d5a3981a347890211bb1bf2439e5c821a63bc9/scripts/generate-agent-catalog.mjs#L43-L79","documentation":"Thrown by the hand-rolled catalog parser in generate-agent-catalog.mjs when it reads a non-empty, non-comment line at indent 0 that does not start with \"- \". The catalog YAML is constrained to a list of top-level rows, each beginning \"- provider: <value>\"; a bare key at column 0 violates that shape.","triggerScenarios":"Editing the agent catalog source file and adding a top-level mapping key (e.g. \"providers:\" as a section header) or a plain \"provider: x\" line without the leading dash, then running the generator script.","commonSituations":"Converting the file from a list-of-maps to a keyed map shape; merge conflict markers (<<<<<<<) left at indent 0; pasting YAML from another doc that uses a different structure.","solutions":["Make every top-level entry a sequence row: prefix it with \"- \" and start with an inline provider value, e.g. \"- provider: anthropic\".","Remove leftover merge-conflict markers or stray lines at column 0 (the error's label:lineNo pinpoints the exact line).","If you need a document-level key, that shape is unsupported — restructure the data so the file stays a flat list of provider rows."],"exampleFix":"# before\nprovider: anthropic\n  model: claude\n\n# after\n- provider: anthropic\n  model: claude","handlingStrategy":"validation","validationCode":"function topLevelRowsOk(text) {\n  return text.split(\"\\n\").every((line) => {\n    const t = line.trimEnd();\n    return t === \"\" || /^ *#/.test(t) || /^- provider: \\S/.test(t) || /^ {2,4} /.test(t);\n  });\n}","typeGuard":null,"tryCatchPattern":"try {\n  parseCatalog(text);\n} catch (err) {\n  if (/expected a top-level/.test(err.message)) {\n    // label:lineNo points at the offending line — open it and add the \"- \" prefix\n  } else throw err;\n}","preventionTips":["Validate catalog edits with the generator script in CI so structure errors never reach release.","Use the exact two-space indentation convention and start every entry with \"- provider: <value>\"."],"tags":["yaml","parser","code-generation","catalog"],"backgroundTag":null,"analyzedSha":"27d5a3981a347890211bb1bf2439e5c821a63bc9","analyzedAt":"2026-08-15T09:26:11.751Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}