{"record":{"id":"f514c3094dbde2fb","repo":"tobi/qmd","slug":"line-line-number-only-one-intent-line-is-allo","errorCode":null,"errorMessage":"Line ${line.number}: only one intent: line is allowed per benchmark query.","messagePattern":"Line (.+?): only one intent: line is allowed per benchmark query\\.","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/bench/bench.ts","lineNumber":62,"sourceCode":"};\n\nfunction parseStructuredQuery(query: string): ParsedStructuredQuery | undefined {\n  const lines = query.split(\"\\n\").map((line, idx) => ({\n    trimmed: line.trim(),\n    number: idx + 1,\n  })).filter(line => line.trimmed.length > 0);\n\n  if (lines.length === 0) return undefined;\n\n  const prefixRe = /^(lex|vec|hyde):\\s*/i;\n  const intentRe = /^intent:\\s*/i;\n  const searches: ExpandedQuery[] = [];\n  let intent: string | undefined;\n\n  for (const line of lines) {\n    if (intentRe.test(line.trimmed)) {\n      if (intent !== undefined) {\n        throw new Error(`Line ${line.number}: only one intent: line is allowed per benchmark query.`);\n      }\n      intent = line.trimmed.replace(intentRe, \"\").trim();\n      if (!intent) {\n        throw new Error(`Line ${line.number}: intent: must include text.`);\n      }\n      continue;\n    }\n\n    const match = line.trimmed.match(prefixRe);\n    if (match) {\n      const type = match[1]!.toLowerCase() as \"lex\" | \"vec\" | \"hyde\";\n      const text = line.trimmed.slice(match[0].length).trim();\n      if (!text) {\n        throw new Error(`Line ${line.number} (${type}:) must include text.`);\n      }\n      searches.push({ type, query: text, line: line.number });\n      continue;\n    }","sourceCodeStart":44,"sourceCodeEnd":80,"githubUrl":"https://github.com/tobi/qmd/blob/dbfd0b4736aeaf761d1a16ca8e424f071df8feb9/src/bench/bench.ts#L44-L80","documentation":"Thrown by parseStructuredQuery in src/bench/bench.ts when a benchmark fixture query document contains more than one 'intent:' line. Each multi-line query in a bench fixture may carry at most a single intent annotation; the second occurrence aborts parsing.","triggerScenarios":"A fixture JSON query whose document string has two lines starting with 'intent:', e.g. 'intent: find setup docs\\nintent: find config docs\\nlex: install'. Passed to runBenchmark via the fixture's queries array.","commonSituations":"Copy-pasting an intent line while editing bench fixtures; merging two query documents into one; appending notes that accidentally use the intent: prefix.","solutions":["Delete the duplicate intent: line so exactly one remains per query document","Merge the two intent descriptions into a single intent: line","Run qmd bench with a small fixture to validate syntax before the full run"],"exampleFix":"// before\n\"lex: install steps\\nintent: setup help\\nintent: installation docs\"\n// after\n\"lex: install steps\\nintent: setup and installation docs\"","handlingStrategy":"validation","validationCode":"const intentCount = (doc.match(/^\\s*intent:/gm) || []).length;\nif (intentCount > 1) throw new RangeError(`fixture query has ${intentCount} intent: lines; max 1`);","typeGuard":"const hasSingleIntent = (doc: string) => (doc.match(/^\\s*intent:/gm) || []).length <= 1;","tryCatchPattern":null,"preventionTips":["Validate fixture query documents with a regex count of intent: lines before qmd bench","Keep fixtures in version control and lint them in CI"],"tags":["bench","fixture-validation","query-syntax"],"backgroundTag":"query-syntax-validation-failed","analyzedSha":"dbfd0b4736aeaf761d1a16ca8e424f071df8feb9","analyzedAt":"2026-08-28T18:07:46.628Z","schemaVersion":2},"datasetVersion":"2026-08-28T21:17:43.275Z"}