tobi/qmd · error · Error
Line ${line.number} (${type}:) contains a newline. Keep each
Error message
Line ${line.number} (${type}:) contains a newline. Keep each query on a single line. What it means
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.
Source
Thrown at src/cli/qmd.ts:2771
throw new Error(`Line ${line.number}: only one intent: line is allowed per query document.`);
}
const text = line.trimmed.replace(intentRe, '').trim();
if (!text) {
throw new Error(`Line ${line.number}: intent: must include text.`);
}
intent = text;
continue;
}
const match = line.trimmed.match(prefixRe);
if (match) {
const type = match[1]!.toLowerCase() as 'lex' | 'vec' | 'hyde';
const text = line.trimmed.slice(match[0].length).trim();
if (!text) {
throw new Error(`Line ${line.number} (${type}:) must include text.`);
}
if (/\r|\n/.test(text)) {
throw new Error(`Line ${line.number} (${type}:) contains a newline. Keep each query on a single line.`);
}
typed.push({ type, query: text, line: line.number });
continue;
}
if (rawLines.length === 1) {
// Single plain line -> implicit expand
return null;
}
throw new Error(`Line ${line.number} is missing a lex:/vec:/hyde:/intent: prefix. Each line in a query document must start with one.`);
}
// intent: alone is not a valid query — must have at least one search
if (intent && typed.length === 0) {
throw new Error('intent: cannot appear alone. Add at least one lex:, vec:, or hyde: line.');
}
View on GitHub (pinned to dbfd0b4736)
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
Example fix
# before lex: how to install and configure # after lex: how to install lex: and configure
Defensive patterns
Strategy: validation
Validate before calling
const bad = doc.split('\n').find(l => /^\s*(lex|vec|hyde):/i.test(l) && /\r|\n/.test(l.replace(/^\s*(lex|vec|hyde):/i, '')));
if (bad || /\r/.test(doc)) throw new Error('newline inside typed query or CRLF endings'); Type guard
const isSingleLineSafe = (doc: string) => !/\r/.test(doc) && doc.split('\n').every(l => !/^\s*(lex|vec|hyde):/i.test(l) || !/[\r\n]/.test(l)); Prevention
- Normalize CRLF to LF (dos2unix) before querying
- Never interpolate multi-line variables into a typed line; split into multiple prefixed lines
When it happens
Trigger: 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).
Common situations: Pasting multi-line questions into a single prefixed line; scripts embedding $'...' strings with \n; CRLF line endings from Windows editors injecting \r.
Related errors
- Line ${line.number} starts with expand:, but query documents
- expand: query must include text.
- Line ${line.number}: only one intent: line is allowed per qu
- Line ${line.number}: intent: must include text.
- Line ${line.number} (${type}:) must include text.
AI-assisted analysis of tobi/qmd@dbfd0b4736 (2026-08-28).
Data as JSON: /api/errors/0335a241631e7193.
Report an issue: GitHub.