{"record":{"id":"fd263c73346a7fc3","repo":"tobi/qmd","slug":"line-line-number-intent-must-include-text","errorCode":null,"errorMessage":"Line ${line.number}: intent: must include text.","messagePattern":"Line (.+?): intent: must include text\\.","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/bench/bench.ts","lineNumber":66,"sourceCode":"    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    }\n\n    if (lines.length === 1) {\n      return undefined;\n    }","sourceCodeStart":48,"sourceCodeEnd":84,"githubUrl":"https://github.com/tobi/qmd/blob/dbfd0b4736aeaf761d1a16ca8e424f071df8feb9/src/bench/bench.ts#L48-L84","documentation":"Thrown when a line in a bench fixture query starts with 'intent:' but has no text after the colon. The parser requires every prefixed line to carry content, so a bare 'intent:' is rejected at that line number.","triggerScenarios":"A query document in the fixture contains 'intent:' with nothing (or only whitespace) after it, e.g. 'lex: foo\\nintent:'.","commonSituations":"Typos or half-edited fixture files; trailing empty intent lines left after deleting intent text.","solutions":["Add descriptive text after intent: or delete the line entirely","Lint fixture files for empty prefixes before running qmd bench"],"exampleFix":"// before\n\"lex: install\\nintent:\"\n// after\n\"lex: install\\nintent: find installation docs\"","handlingStrategy":"validation","validationCode":"if (/^\\s*intent:\\s*$/m.test(doc)) throw new Error('empty intent: line in fixture query');","typeGuard":"const noEmptyIntent = (doc: string) => !/^\\s*intent:\\s*$/m.test(doc);","tryCatchPattern":null,"preventionTips":["Reject lines matching ^prefix:\\s*$ when authoring fixtures","Run qmd bench on a tiny smoke fixture first"],"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"}