{"record":{"id":"95f2694dac68f724","repo":"JuliusBrussee/caveman","slug":"label-lineno-duplicate-key-entry-key","errorCode":null,"errorMessage":"${label}:${lineNo}: duplicate key \"${entry.key}\"","messagePattern":"(.+?):(.+?): duplicate key \"(.+?)\"","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"scripts/generate-agent-catalog.mjs","lineNumber":75,"sourceCode":"    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;\n      } else {\n        blockKey = null;\n        row[entry.key] = entry.value;\n      }\n      continue;\n    }\n    if (indent === 4) {\n      if (blockKey === null) throw new Error(`${label}:${lineNo}: nested line without an open block`);\n      if (dash) {\n        if (row[blockKey] === undefined) row[blockKey] = [];\n        if (!Array.isArray(row[blockKey])) throw new Error(`${label}:${lineNo}: \"${blockKey}\" mixes map and sequence entries`);\n        row[blockKey].push(rest);\n        continue;\n      }","sourceCodeStart":57,"sourceCodeEnd":93,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/27d5a3981a347890211bb1bf2439e5c821a63bc9/scripts/generate-agent-catalog.mjs#L57-L93","documentation":"Thrown by the catalog parser when the same key appears twice at indent 2 within one provider row. Because the parser builds a plain object per row, a duplicate key would silently overwrite the earlier value; rejecting it preserves the source's integrity and makes the generated catalog deterministic.","triggerScenarios":"Adding a property to a row that already defines it, e.g. two \"model:\" lines under one provider; pasting a block that re-declares keys already present higher in the row.","commonSituations":"Appending new config without scrolling to check the row's existing keys; merge conflicts resolved by keeping both sides' lines.","solutions":["Search the current row (from its \"- provider:\" line to the next one) for the duplicate key named in the error and delete or rename one occurrence.","If you meant to have multiple values, use the two-level block form: \"  key:\" with \"    - value\" items."],"exampleFix":"# before\n- provider: anthropic\n  model: claude-4\n  model: claude-haiku\n\n# after\n- provider: anthropic\n  models:\n    - claude-4\n    - claude-haiku","handlingStrategy":"validation","validationCode":"function noDuplicateRowKeys(text) {\n  const seen = new Set(); let row = 0;\n  for (const line of text.split(\"\\n\")) {\n    if (/^- provider: /.test(line)) seen.clear();\n    const m = /^ {2}([A-Za-z_][A-Za-z0-9_]*):/.exec(line);\n    if (m) { if (seen.has(m[1])) return false; seen.add(m[1]); }\n  }\n  return true;\n}","typeGuard":null,"tryCatchPattern":"try {\n  parseCatalog(text);\n} catch (err) {\n  if (/duplicate key \"/.test(err.message) && !err.message.includes(\".\")) {\n    // remove or rename the duplicated indent-2 key in the current row\n  } else throw err;\n}","preventionTips":["Sort or lint keys within a row so duplicates are visually obvious.","After merge conflicts, scan each row for repeated keys before running the generator."],"tags":["yaml","parser","duplicate-key","code-generation"],"backgroundTag":null,"analyzedSha":"27d5a3981a347890211bb1bf2439e5c821a63bc9","analyzedAt":"2026-08-15T09:26:11.751Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}