{"record":{"id":"2c344f4d7b2e43e9","repo":"tobi/qmd","slug":"location-search-type-queries-must-be-sing","errorCode":null,"errorMessage":"${location} (${search.type}): queries must be single-line. Remove newline characters.","messagePattern":"(.+?) \\((.+?)\\): queries must be single-line\\. Remove newline characters\\.","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/store.ts","lineNumber":5883,"sourceCode":"  options?: StructuredSearchOptions\n): Promise<HybridQueryResult[]> {\n  const limit = options?.limit ?? 10;\n  const minScore = options?.minScore ?? 0;\n  const candidateLimit = options?.candidateLimit ?? RERANK_CANDIDATE_LIMIT;\n  const explain = options?.explain ?? false;\n  const intent = options?.intent;\n  const skipRerank = options?.skipRerank ?? false;\n  const hooks = options?.hooks;\n\n  const collections = options?.collections;\n\n  if (searches.length === 0) return [];\n\n  // Validate queries before executing\n  for (const search of searches) {\n    const location = search.line ? `Line ${search.line}` : 'Structured search';\n    if (/[\\r\\n]/.test(search.query)) {\n      throw new Error(`${location} (${search.type}): queries must be single-line. Remove newline characters.`);\n    }\n    if (search.type === 'lex') {\n      const error = validateLexQuery(search.query);\n      if (error) {\n        throw new Error(`${location} (lex): ${error}`);\n      }\n    } else if (search.type === 'vec' || search.type === 'hyde') {\n      const error = validateSemanticQuery(search.query);\n      if (error) {\n        throw new Error(`${location} (${search.type}): ${error}`);\n      }\n    }\n  }\n\n  const rankedLists: RankedResult[][] = [];\n  const rankedListMeta: RankedListMeta[] = [];\n  const docidMap = new Map<string, string>(); // filepath -> docid\n  const hasVectors = !!store.db.prepare(","sourceCodeStart":5865,"sourceCodeEnd":5901,"githubUrl":"https://github.com/tobi/qmd/blob/dbfd0b4736aeaf761d1a16ca8e424f071df8feb9/src/store.ts#L5865-L5901","documentation":"The multi-search validator rejects any query containing \\r or \\n because each search's query must fit on a single line (they are interpolated into single-line SQL/FTS statements). The error is prefixed with the search's line number or 'Structured search'.","triggerScenarios":"Passing a searches array where any entry's query string contains a newline — e.g. a template literal spanning lines, or a user query pasted with a trailing newline into searchMulti().","commonSituations":"Multi-line JS template strings used for queries; user input from textareas passed directly; log/env strings with embedded \\n.","solutions":["Strip newlines before passing: query.replace(/[\\r\\n]+/g, ' ').trim()","Split multi-line input into separate search entries if each line is a distinct query","Validate input client-side before calling searchMulti"],"exampleFix":"// before\nsearchMulti([{ type: 'lex', query: multiLineString }]);\n// after\nsearchMulti([{ type: 'lex', query: multiLineString.replace(/[\\r\\n]+/g, ' ').trim() }]);","handlingStrategy":"validation","validationCode":"const clean = q.replace(/[\\r\\n]+/g, ' ').trim(); if (!/[\\r\\n]/.test(clean)) searchMulti([{ type, query: clean }]);","typeGuard":"const isSingleLine = (q: string) => !/[\\r\\n]/.test(q);","tryCatchPattern":null,"preventionTips":["Normalize user input to single lines at the boundary","Never paste multi-line template literals as queries","Add form-level validation for textareas"],"tags":["query","validation","newline","search"],"backgroundTag":"input-validation-failed","analyzedSha":"dbfd0b4736aeaf761d1a16ca8e424f071df8feb9","analyzedAt":"2026-08-28T18:07:46.628Z","schemaVersion":2},"datasetVersion":"2026-08-28T21:17:43.275Z"}