{"record":{"id":"80e53ef5cbf0f43f","repo":"chroma-core/chroma","slug":"mul-requires-at-least-one-rank-expression","errorCode":null,"errorMessage":"Mul requires at least one rank expression","messagePattern":"Mul requires at least one rank expression","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"clients/new-js/packages/chromadb/src/execution/expression/rank.ts","lineNumber":521,"sourceCode":"export const Sum = (...inputs: RankInput[]): RankExpression => {\n  if (inputs.length === 0) {\n    throw new Error(\"Sum requires at least one rank expression\");\n  }\n  const expressions = inputs.map((rank, index) =>\n    requireRank(rank, `Sum operand ${index}`),\n  );\n  return SumRankExpression.create(expressions);\n};\n\nexport const Sub = (left: RankInput, right: RankInput): RankExpression =>\n  new SubRankExpression(\n    requireRank(left, \"Sub left\"),\n    requireRank(right, \"Sub right\"),\n  );\n\nexport const Mul = (...inputs: RankInput[]): RankExpression => {\n  if (inputs.length === 0) {\n    throw new Error(\"Mul requires at least one rank expression\");\n  }\n  const expressions = inputs.map((rank, index) =>\n    requireRank(rank, `Mul operand ${index}`),\n  );\n  return MulRankExpression.create(expressions);\n};\n\nexport const Div = (left: RankInput, right: RankInput): RankExpression =>\n  new DivRankExpression(\n    requireRank(left, \"Div left\"),\n    requireRank(right, \"Div right\"),\n  );\n\nexport const Abs = (input: RankInput): RankExpression =>\n  requireRank(input, \"Abs\").abs();\n\nexport const Exp = (input: RankInput): RankExpression =>\n  requireRank(input, \"Exp\").exp();","sourceCodeStart":503,"sourceCodeEnd":539,"githubUrl":"https://github.com/chroma-core/chroma/blob/aecdd12c8a891610db8653630b066b32ceb678b5/clients/new-js/packages/chromadb/src/execution/expression/rank.ts#L503-L539","documentation":"Thrown by the Mul rank factory (rank.ts:521) when called with zero arguments. Mul multiplies two or more rank expressions and needs at least one operand to emit {$mul: [...]}. As with Sum, expr.multiply() with no args returns expr, but the factory Mul() with no args throws.","triggerScenarios":"Calling Mul(); spreading a dynamic operand list Mul(...factors) where the list is empty — e.g. every multiplicative boost was disabled or the boost array came back empty from config.","commonSituations":"Product-of-boosts pipelines (freshness * popularity * relevance) where all boosts are optional; multiplying user-selected factors where none are selected; refactoring that left a call site with only a spread of an optional array.","solutions":["Pass at least one operand: Mul(a, b)","Use the multiplicative identity for the empty case: Mul(...(factors.length ? factors : [1]))","Skip the multiplication step when the factor list is empty"],"exampleFix":"// before\nconst rank = base.multiply(...boosts); // ok, but Mul(...boosts) with [] throws\nconst rank2 = Mul(...boosts); // throws when boosts is []\n\n// after\nconst rank2 = Mul(...(boosts.length ? boosts : [1]));","handlingStrategy":"validation","validationCode":"const rank = factors.length\n  ? Mul(...factors)\n  : Val(1); // multiplicative identity","typeGuard":null,"tryCatchPattern":"try {\n  const rank = Mul(...factors);\n} catch (e) {\n  if (e instanceof Error && e.message.includes('Mul requires')) {\n    return Val(1);\n  }\n  throw e;\n}","preventionTips":["Use Val(1) as the multiplicative identity for empty factor lists","Prefer base.multiply(...boosts) when a guaranteed base operand exists"],"tags":["mul","rank-expression","empty-arguments","input-validation"],"backgroundTag":"missing-required-argument","analyzedSha":"aecdd12c8a891610db8653630b066b32ceb678b5","analyzedAt":"2026-08-16T21:53:27.228Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}