{"id":"bba08912902135d9","repo":"prisma/prisma","slug":"proximity-chain-trailing-distance-with-no-followi","errorCode":null,"errorMessage":"proximity-chain: trailing distance with no following term at position ${i + 1}","messagePattern":"proximity-chain: trailing distance with no following term at position (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"examples/paradedb-demo/src/main.ts","lineNumber":30,"sourceCode":"import { bm25TopByScore } from './queries/bm25-top-by-score';\n\nfunction parseProximityChainArgs(args: readonly string[]): {\n  readonly start: string;\n  readonly steps: readonly ProximityChainStep[];\n} {\n  if (args.length < 3 || args.length % 2 !== 1) {\n    throw new Error('Usage: pnpm start -- proximity-chain <t0> <d1> <t1> [<d2> <t2> ...]');\n  }\n  const [start, ...rest] = args;\n  if (start === undefined) {\n    throw new Error('proximity-chain: <t0> is required');\n  }\n  const steps: ProximityChainStep[] = [];\n  for (let i = 0; i < rest.length; i += 2) {\n    const distRaw = rest[i];\n    const term = rest[i + 1];\n    if (distRaw === undefined || term === undefined) {\n      throw new Error(\n        `proximity-chain: trailing distance with no following term at position ${i + 1}`,\n      );\n    }\n    const ordered = distRaw.startsWith('>');\n    const distStr = ordered ? distRaw.slice(1) : distRaw;\n    const distance = Number.parseInt(distStr, 10);\n    if (!Number.isInteger(distance) || distance < 0) {\n      throw new Error(\n        `proximity-chain: distance at position ${i + 1} must be a non-negative integer (optionally prefixed '>' for ordered); got '${distRaw}'`,\n      );\n    }\n    steps.push({ distance, term, ordered });\n  }\n  return { start, steps };\n}\n\nconst argv = process.argv.slice(2).filter((arg) => arg !== '--');\nconst [cmd, ...args] = argv;","sourceCodeStart":12,"sourceCodeEnd":48,"githubUrl":"https://github.com/prisma/prisma/blob/1243cdffbec0506c595ac8fd5865fe258c336fa0/examples/paradedb-demo/src/main.ts#L12-L48","documentation":"Thrown by parseProximityChainArgs when, while iterating distance/term pairs, a distance token has no corresponding term. Because the loop steps by 2, this only happens when the leading args.length/parity check is bypassed (e.g. a direct caller passes an even-length array) or when an array element is explicitly undefined. It is a structural-consistency guard for the pairing loop.","triggerScenarios":"Calling parseProximityChainArgs with an even number of rest arguments (after the start term), so the last distance token (rest[i]) has rest[i+1] (term) undefined. The reported position is i+1 within the rest array.","commonSituations":"Direct programmatic callers passing an even-length args array; via the normal CLI this is pre-empted by error [16]. Can appear if someone refactors the length guard or feeds args from a parsed source that drops empty strings.","solutions":["Ensure the args after the start term come in distance/term pairs (even count of rest args).","If invoked via CLI, fix the invocation to satisfy the usage message (error [16]) first.","For direct callers, normalize args (strip holes/undefined) and assert even pairing before calling.","Add a trailing term to consume the dangling distance, or drop the trailing distance."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"for (let i = 0; i < rest.length; i += 2) {\n  if (rest[i] === undefined || rest[i + 1] === undefined) {\n    console.error(`trailing distance with no following term at position ${i + 1}`);\n    process.exit(1);\n  }\n}","typeGuard":"const isCompletePairs = (a: readonly unknown[]): a is string[] =>\n  a.length % 2 === 0 && a.every((x) => typeof x === 'string');","tryCatchPattern":"try {\n  const { start, steps } = parseProximityChainArgs(args);\n} catch (error) {\n  if (error instanceof Error && error.message.includes('trailing distance')) {\n    console.error(error.message);\n    process.exit(1);\n  }\n  throw error;\n}","preventionTips":["The [16] arity check (odd total length) should already make this unreachable — treat it as a defensive guard and keep both checks in sync.","When building argv programmatically, always push (distance, term) pairs together to avoid orphan distances.","Unit-test the parser with edge cases like a trailing distance token to confirm the message fires.","Log the offending position in the error so the user can map it back to their command line."],"tags":["cli","arguments","validation","defensive","paradedb","examples"],"analyzedSha":"1243cdffbec0506c595ac8fd5865fe258c336fa0","analyzedAt":"2026-08-01T19:42:02.087Z","schemaVersion":2}