tobi/qmd · error · Error

Line ${line.number} is missing a lex:/vec:/hyde:/intent: pre

Error message

Line ${line.number} is missing a lex:/vec:/hyde:/intent: prefix. Each line in a query document must start with one.

What it means

Thrown when parsing a multi-line query document where a line does not start with one of the required prefixes: lex:, vec:, hyde:, or intent:. The query-document format requires every line (after the first, which gets implicit expansion) to be explicitly typed so the CLI knows which retrieval strategy to use for it.

Source

Thrown at src/cli/qmd.ts:2782

    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.');
  }

  return typed.length > 0 ? { searches: typed, intent } : null;
}

function search(query: string, opts: OutputOptions): void {
  const db = getDb();

  // Validate collection filter (supports multiple -c flags)
  // Use default collections if none specified
  const collectionNames = resolveCollectionFilter(opts.collection, true);

  // Use large limit for --all, otherwise fetch more than needed and let outputResults filter

View on GitHub (pinned to dbfd0b4736)

Solutions

  1. Add a lex:, vec:, hyde:, or intent: prefix to the offending line (the error names the line number)
  2. Collapse the query to a single plain line to get implicit expand behavior
  3. Check the query-document syntax with `qmd query --help` or the skill docs

Example fix

# before
how do I chunk markdown
vec:embedding models
# after
lex:how do I chunk markdown
vec:embedding models
Defensive patterns

Strategy: validation

Validate before calling

const PREFIX = /^(lex:|vec:|hyde:|intent:)/;
function validateQueryDoc(raw: string): { ok: true } | { ok: false; line: number } {
  const lines = raw.split(/\r?\n/).filter((l) => l.trim() !== "");
  if (lines.length <= 1) return { ok: true };
  for (let i = 0; i < lines.length; i++) {
    if (!PREFIX.test(lines[i])) return { ok: false, line: i + 1 };
  }
  return { ok: true };
}

Type guard

null

Try / catch

null

Prevention

When it happens

Trigger: Running `qmd query` with a multi-line query document (e.g. via a query file or multi-line argument) where at least one line lacks a lex:/vec:/hyde:/intent: prefix. A single plain line is implicitly expanded, but two or more lines forces strict prefix validation.

Common situations: Writing a multi-line query file for hybrid search and forgetting prefixes on the second line; upgrading from an older version that allowed plain multi-line queries; mixing a natural-language question with typed lines.

Related errors


AI-assisted analysis of tobi/qmd@dbfd0b4736 (2026-08-28). Data as JSON: /api/errors/3c3c7e35a65e0cf5. Report an issue: GitHub.