{"record":{"id":"0335a241631e7193","repo":"tobi/qmd","slug":"line-line-number-type-contains-a-newline","errorCode":null,"errorMessage":"Line ${line.number} (${type}:) contains a newline. Keep each query on a single line.","messagePattern":"Line (.+?) \\((.+?):\\) contains a newline\\. Keep each query on a single line\\.","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/cli/qmd.ts","lineNumber":2771,"sourceCode":"        throw new Error(`Line ${line.number}: only one intent: line is allowed per query document.`);\n      }\n      const text = line.trimmed.replace(intentRe, '').trim();\n      if (!text) {\n        throw new Error(`Line ${line.number}: intent: must include text.`);\n      }\n      intent = text;\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      if (/\\r|\\n/.test(text)) {\n        throw new Error(`Line ${line.number} (${type}:) contains a newline. Keep each query on a single line.`);\n      }\n      typed.push({ type, query: text, line: line.number });\n      continue;\n    }\n\n    if (rawLines.length === 1) {\n      // Single plain line -> implicit expand\n      return null;\n    }\n\n    throw new Error(`Line ${line.number} is missing a lex:/vec:/hyde:/intent: prefix. Each line in a query document must start with one.`);\n  }\n\n  // intent: alone is not a valid query — must have at least one search\n  if (intent && typed.length === 0) {\n    throw new Error('intent: cannot appear alone. Add at least one lex:, vec:, or hyde: line.');\n  }\n","sourceCodeStart":2753,"sourceCodeEnd":2789,"githubUrl":"https://github.com/tobi/qmd/blob/dbfd0b4736aeaf761d1a16ca8e424f071df8feb9/src/cli/qmd.ts#L2753-L2789","documentation":"Thrown by the CLI query-document parser when the text of a lex:/vec:/hyde: line contains a carriage return or newline. Each typed query must stay on a single physical line; the parser refuses embedded line breaks inside query text.","triggerScenarios":"Interpolating a multi-line shell variable into a typed line, or a fixture/query file where the text after the prefix spans lines (e.g. 'lex: install\\n  continue here' without a prefix on the continuation).","commonSituations":"Pasting multi-line questions into a single prefixed line; scripts embedding $'...' strings with \\n; CRLF line endings from Windows editors injecting \\r.","solutions":["Put the continuation on its own prefixed line: 'lex: install\\nlex: continue here'","Strip \\r from CRLF files: dos2unix or sed -i 's/\\r$//'","For multi-clause queries use intent: plus one typed line per clause"],"exampleFix":"# before\nlex: how to install\n  and configure\n# after\nlex: how to install\nlex: and configure","handlingStrategy":"validation","validationCode":"const bad = doc.split('\\n').find(l => /^\\s*(lex|vec|hyde):/i.test(l) && /\\r|\\n/.test(l.replace(/^\\s*(lex|vec|hyde):/i, '')));\nif (bad || /\\r/.test(doc)) throw new Error('newline inside typed query or CRLF endings');","typeGuard":"const isSingleLineSafe = (doc: string) => !/\\r/.test(doc) && doc.split('\\n').every(l => !/^\\s*(lex|vec|hyde):/i.test(l) || !/[\\r\\n]/.test(l));","tryCatchPattern":null,"preventionTips":["Normalize CRLF to LF (dos2unix) before querying","Never interpolate multi-line variables into a typed line; split into multiple prefixed lines"],"tags":["query","cli","query-syntax","line-endings"],"backgroundTag":"query-syntax-validation-failed","analyzedSha":"dbfd0b4736aeaf761d1a16ca8e424f071df8feb9","analyzedAt":"2026-08-28T18:07:46.628Z","schemaVersion":2},"datasetVersion":"2026-08-28T21:17:43.275Z"}