chroma-core/chroma · error · TypeError

Knn default must be a finite number

Error message

Knn default must be a finite number

What it means

Guard in normalizeKnnOptions (rank.ts:419) requiring Knn()'s `default` option — the score substituted for documents that lack an embedding — to be a finite number. In the current code this branch is effectively unreachable: the preceding requireNumber call (rank.ts:417, message 'Knn default must be a number') already rejects non-numbers, NaN, and Infinity before this check runs. If you pass NaN or Infinity you will actually see the sibling 'must be a number' message; this message exists as defensive redundancy.

Source

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

      values: sparse.values.slice(),
    };
  } else {
    query = normalizeDenseVector(queryInput as IterableInput<number>);
  }

  const key =
    options.key instanceof Key ? options.key.name : options.key ?? "#embedding";
  if (typeof key !== "string") {
    throw new TypeError("Knn key must be a string or Key instance");
  }

  const defaultValue =
    options.default === null || options.default === undefined
      ? undefined
      : requireNumber(options.default, "Knn default must be a number");

  if (defaultValue !== undefined && !Number.isFinite(defaultValue)) {
    throw new TypeError("Knn default must be a finite number");
  }

  return {
    query:
      Array.isArray(query) || typeof query === "string"
        ? query
        : deepClone(query),
    key,
    limit,
    defaultValue,
    returnRank: options.returnRank ?? false,
  };
};

const requireRank = (input: RankInput, context: string): RankExpression => {
  const result = RankExpression.from(input);
  if (!result) {
    throw new TypeError(`${context} must be a rank expression`);

View on GitHub (pinned to aecdd12c8a)

Solutions

  1. Pass a finite number as default (0 and negatives are allowed)
  2. Omit default, or pass null/undefined, if you do not want a fallback score
  3. Fix the upstream computation producing NaN/Infinity (e.g. guard a division with Number.isFinite before assigning)

Example fix

// before
const rank = Knn({ query: vec, default: someRatio }); // someRatio may be NaN/Infinity

// after
const rank = Knn({
  query: vec,
  default: Number.isFinite(someRatio) ? someRatio : 0,
});
Defensive patterns

Strategy: validation

Validate before calling

const rank = Knn({
  query: vec,
  default: Number.isFinite(cfg.defaultScore) ? cfg.defaultScore : undefined,
});

Type guard

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

Try / catch

try {
  const rank = Knn({ query: vec, default: d });
} catch (e) {
  if (e instanceof TypeError && e.message.includes('Knn default')) {
    return Knn({ query: vec }); // no default score
  }
  throw e;
}

Prevention

When it happens

Trigger: Intended trigger: Knn({ query, default: NaN }), default: Infinity, or default: -Infinity. In practice those raise 'Knn default must be a number' (requireNumber, rank.ts:417) first, so you should never observe this exact message from the shipped code. null/undefined are legal and mean 'no default'.

Common situations: Defaults computed from user input via parseFloat that yield NaN (parseFloat('abc')); scoring defaults sourced from config that contain Infinity after division by zero upstream; passing 0 or a negative number is fine — only NaN/Infinity class values are rejected.

Related errors


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