{"record":{"id":"7f49b952eddb75dd","repo":"JuliusBrussee/caveman","slug":"label-lineno-empty-value","errorCode":null,"errorMessage":"${label}:${lineNo}: empty value","messagePattern":"(.+?):(.+?): empty value","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"scripts/generate-agent-catalog.mjs","lineNumber":118,"sourceCode":"      if (Object.prototype.hasOwnProperty.call(row[blockKey], entry.key)) {\n        throw new Error(`${label}:${lineNo}: duplicate key \"${blockKey}.${entry.key}\"`);\n      }\n      row[blockKey][entry.key] = entry.value;\n      continue;\n    }\n    throw new Error(`${label}:${lineNo}: unexpected indent of ${indent} spaces`);\n  }\n  return rows;\n}\n\nfunction splitKeyValue(text, label, lineNo) {\n  const match = /^([A-Za-z_][A-Za-z0-9_]*):(?: (.*))?$/.exec(text);\n  if (match === null) throw new Error(`${label}:${lineNo}: cannot read \"${text}\" as a \"key: value\" pair`);\n  return { key: match[1], value: match[2] === undefined ? undefined : scalar(match[2], label, lineNo) };\n}\n\nfunction scalar(text, label, lineNo) {\n  if (text === \"\") throw new Error(`${label}:${lineNo}: empty value`);\n  if (text === \"null\") return null;\n  if (text === \"true\") return true;\n  if (text === \"false\") return false;\n  if (/^-?(0|[1-9][0-9]*)(\\.[0-9]+)?([eE][+-]?[0-9]+)?$/.test(text)) {\n    const value = Number(text);\n    if (!Number.isFinite(value)) throw new Error(`${label}:${lineNo}: \"${text}\" is not a finite number`);\n    return value;\n  }\n  return text;\n}\n\n/** Selects the priced, region-agnostic, USD rows the agent catalog can honestly carry. */\nexport function selectRows(rows, label = CATALOG_LABEL) {\n  const selected = [];\n  const skippedByKey = new Map();\n  const seen = new Set();\n  const record = (key) => {\n    let entry = skippedByKey.get(key);","sourceCodeStart":100,"sourceCodeEnd":136,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/27d5a3981a347890211bb1bf2439e5c821a63bc9/scripts/generate-agent-catalog.mjs#L100-L136","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"# before\n  output_per_million: \n# after\n  output_per_million: 15","handlingStrategy":"validation","validationCode":"// Reject `key: ` lines with an empty captured value before generating.\nconst bad = text.split(\"\\n\").flatMap((line, i) => {\n  const m = /^([A-Za-z_][A-Za-z0-9_]*): (.*)$/.exec(line.replace(/\\s+$/, \"\"));\n  return m && m[2] === \"\" ? [i + 1] : [];\n});","typeGuard":null,"tryCatchPattern":"catch (error) {\n  if (/empty value$/.test(error.message)) { const [, lineNo] = error.message.match(/:(\\d+):/); fixEmptyValue(lineNo); }\n  else throw error;\n}","preventionTips":["Configure your editor to trim trailing whitespace on save.","Never leave `key: ` skeletons in the catalog; write the value or delete the line."],"tags":["yaml","parsing","whitespace","catalog"],"backgroundTag":null,"analyzedSha":"27d5a3981a347890211bb1bf2439e5c821a63bc9","analyzedAt":"2026-08-15T09:26:11.751Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}