{"record":{"id":"c1033f3c7ccf09f5","repo":"chroma-core/chroma","slug":"number-of-weights-must-match-number-of-ranks","errorCode":null,"errorMessage":"Number of weights must match number of ranks","messagePattern":"Number of weights must match number of ranks","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"clients/new-js/packages/chromadb/src/execution/expression/rank.ts","lineNumber":476,"sourceCode":"  weights,\n  normalize = false,\n}: RrfOptions): RankExpression => {\n  if (!Number.isInteger(k) || k <= 0) {\n    throw new TypeError(\"Rrf k must be a positive integer\");\n  }\n  if (!Array.isArray(ranks) || ranks.length === 0) {\n    throw new TypeError(\"Rrf requires at least one rank expression\");\n  }\n\n  const expressions = ranks.map((rank, index) =>\n    requireRank(rank, `ranks[${index}]`),\n  );\n\n  let weightValues = weights\n    ? weights.slice()\n    : new Array(expressions.length).fill(1);\n  if (weightValues.length !== expressions.length) {\n    throw new Error(\"Number of weights must match number of ranks\");\n  }\n  if (weightValues.some((value) => typeof value !== \"number\" || value < 0)) {\n    throw new TypeError(\"Weights must be non-negative numbers\");\n  }\n\n  if (normalize) {\n    const total = weightValues.reduce((sum, value) => sum + value, 0);\n    if (total <= 0) {\n      throw new Error(\n        \"Weights must sum to a positive value when normalize=true\",\n      );\n    }\n    weightValues = weightValues.map((value) => value / total);\n  }\n\n  const terms = expressions.map((rank, index) => {\n    const weight = weightValues[index];\n    const numerator = Val(weight);","sourceCodeStart":458,"sourceCodeEnd":494,"githubUrl":"https://github.com/chroma-core/chroma/blob/aecdd12c8a891610db8653630b066b32ceb678b5/clients/new-js/packages/chromadb/src/execution/expression/rank.ts#L458-L494","documentation":"Thrown by Rrf (rank.ts:476) when the optional `weights` array length differs from the `ranks` array length. Weights are applied per-rank in the fusion formula, so the two lists must correspond one-to-one. This is a plain Error (not a TypeError) and is raised before weight values themselves are validated.","triggerScenarios":"Calling Rrf({ ranks: [a, b, c], weights: [1, 1] }) — three rankers but two weights; adding a retriever without extending the weights array; weights built from a different source (config keyed by feature list) that drifted out of sync with the ranks list.","commonSituations":"Hard-coded weight arrays next to dynamically assembled retriever lists; feature-flag code that appends a ranker but not its weight; refactoring that reorders one array but not the other; copy-pasted weights from an example with a different retriever count.","solutions":["Match lengths: supply one weight per rank, e.g. Rrf({ ranks: [a, b], weights: [0.7, 0.3] })","For equal weighting, omit weights entirely — the default is all 1s","Derive weights from the ranks list itself (e.g. ranks.map((_, i) => config[i] ?? 1)) so they cannot drift"],"exampleFix":"// before\nconst fused = Rrf({ ranks: [bm25, dense, mmr], weights: [0.5, 0.5] });\n\n// after\nconst fused = Rrf({ ranks: [bm25, dense, mmr], weights: [0.4, 0.4, 0.2] });\n// or omit weights for uniform weighting","handlingStrategy":"validation","validationCode":"const weights = configuredWeights.length === ranks.length\n  ? configuredWeights\n  : undefined; // fall back to uniform\nconst fused = Rrf({ ranks, weights });","typeGuard":null,"tryCatchPattern":"try {\n  const fused = Rrf({ ranks, weights });\n} catch (e) {\n  if (e instanceof Error && e.message.includes('must match number of ranks')) {\n    return Rrf({ ranks }); // uniform weights\n  }\n  throw e;\n}","preventionTips":["Omit weights for equal emphasis — default is all 1s","Derive weights from the ranks list so lengths cannot drift","This is a plain Error, not a TypeError — match with instanceof Error"],"tags":["rrf","weights","length-mismatch","input-validation"],"backgroundTag":"array-length-mismatch","analyzedSha":"aecdd12c8a891610db8653630b066b32ceb678b5","analyzedAt":"2026-08-16T21:53:27.228Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}