chroma-core/chroma · error · TypeError

${message}

Error message

${message}

What it means

This is the shared requireNumber guard in rank.ts: it throws a TypeError with a caller-supplied message whenever a value is not a number, NaN, or non-finite (Infinity/-Infinity). The concrete messages you will see are "Val requires a numeric value" (from Val(value)) and "Knn default must be a number" (from Knn({ default })). It exists because JS callers and any-typed values can bypass the TypeScript number signatures.

Source

Thrown at clients/new-js/packages/chromadb/src/execution/expression/rank.ts:19

import type { SparseVector } from "../../api";
import { deepClone, isPlainObject, IterableInput } from "./common";
import { Key } from "./key";

export type RankLiteral = Record<string, unknown>;
export type RankInput =
  | RankExpression
  | RankLiteral
  | number
  | null
  | undefined;

const requireNumber = (value: unknown, message: string): number => {
  if (
    typeof value !== "number" ||
    Number.isNaN(value) ||
    !Number.isFinite(value)
  ) {
    throw new TypeError(message);
  }
  return value;
};

abstract class RankExpressionBase {
  public abstract toJSON(): Record<string, unknown>;

  public add(...others: RankInput[]): RankExpression {
    if (others.length === 0) {
      return this as unknown as RankExpression;
    }
    const expressions = [
      this as unknown as RankExpression,
      ...others.map((item, index) => requireRank(item, `add operand ${index}`)),
    ];
    return SumRankExpression.create(expressions);
  }

View on GitHub (pinned to aecdd12c8a)

Solutions

  1. Coerce before calling: Val(Number(weight)) with an explicit fallback for NaN
  2. Validate finiteness at the source: if (!Number.isFinite(x)) use a default
  3. For Knn defaults, pass a literal number (e.g. 0) or omit/null the option entirely

Example fix

// before
const boost = Val(cfg.weight); // cfg.weight = "1.5" (string) -> TypeError

// after
const weight = Number(cfg.weight);
const boost = Val(Number.isFinite(weight) ? weight : 1);
Defensive patterns

Strategy: validation

Validate before calling

const toFiniteNumber = (v: unknown, fallback: number): number =>
  typeof v === "number" && Number.isFinite(v) ? v : fallback;

const boost = Val(toFiniteNumber(cfg.weight, 1));
const knn = Knn({ query, default: toFiniteNumber(cfg.defaultScore, 0) });

Type guard

const isFiniteNumber = (v: unknown): v is number =>
  typeof v === "number" && Number.isFinite(v);

Try / catch

try {
  const expr = Val(weight);
} catch (e) {
  if (e instanceof TypeError && /numeric value|must be a number/.test(e.message)) {
    // coerce the source value (Number()) or substitute a default and rebuild
  } else throw e;
}

Prevention

When it happens

Trigger: Val(NaN), Val("1.5"), or Val(Infinity) when building rank constants. Knn({ query, default: "0" }) or Knn({ default: NaN }) when supplying a default score for records missing embeddings.

Common situations: Rank weights parsed from config or LLM output as strings ("1.5") instead of numbers. Division producing Infinity (x / 0) before feeding Val(). optional-chained values that turn out to be undefined and are passed as the Knn default.

Related errors


AI-assisted analysis of chroma-core/chroma@aecdd12c8a (2026-08-16). Data as JSON: /api/errors/af3929bdbc16a844. Report an issue: GitHub.