tobi/qmd · error · Error

Line is missing a lex:/vec:/hyde:/intent: prefix. Each line…

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.

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.

Appendix: 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)