mem0ai/mem0 · error

threshold must be a valid number

Error message

threshold must be a valid number

What it means

Thrown by validateSearchParams when the threshold option of Memory.search() is defined but is not a number (wrong type) or is NaN. threshold gates the similarity cutoff for search results, so a non-numeric value — typically a string from env/config files — is rejected before any vector query runs.

Source

Thrown at mem0-ts/src/oss/src/memory/index.ts:187

      `Invalid ${name}: cannot be empty or whitespace-only. Provide a valid identifier.`,
    );
  }
  if (/\s/.test(trimmed)) {
    throw new Error(
      `Invalid ${name}: cannot contain whitespace. Provide a valid identifier without spaces.`,
    );
  }
  return trimmed;
}

/**
 * Validates search parameters.
 * @throws Error if threshold or topK are invalid
 */
function validateSearchParams(threshold?: number, topK?: number): void {
  if (threshold !== undefined) {
    if (typeof threshold !== "number" || isNaN(threshold)) {
      throw new Error("threshold must be a valid number");
    }
    if (threshold < 0 || threshold > 1) {
      throw new Error(
        `Invalid threshold: ${threshold}. Must be between 0 and 1 (inclusive).`,
      );
    }
  }
  if (topK !== undefined) {
    if (typeof topK !== "number" || isNaN(topK) || !Number.isInteger(topK)) {
      throw new Error("topK must be a valid integer");
    }
    if (topK < 0) {
      throw new Error(`Invalid topK: ${topK}. Must be a non-negative integer.`);
    }
  }
}

export class Memory {

View on GitHub (pinned to 001c235229)

Solutions

  1. Coerce before calling: threshold: Number(opts.threshold) and check Number.isFinite first.
  2. Validate at the API boundary: reject or default non-numeric threshold in your HTTP/config layer.
  3. If threshold is optional in your app, only include the key when a valid number exists (don't pass undefined-as-string).
  4. Add a unit test for options parsing so string thresholds never reach Memory.search.

Example fix

// before
const results = await memory.search(query, { threshold: req.query.threshold }); // '0.5' string -> throws

// after
const rawThreshold = req.query.threshold;
const threshold = rawThreshold === undefined ? undefined : Number(rawThreshold);
if (threshold !== undefined && !Number.isFinite(threshold)) {
  throw new TypeError('threshold must be numeric');
}
const results = await memory.search(query, { threshold });
Defensive patterns

Strategy: validation

Validate before calling

function parseThreshold(raw: unknown): number | undefined {
  if (raw === undefined || raw === null) return undefined;
  const n = Number(raw);
  if (!Number.isFinite(n)) throw new TypeError('threshold must be numeric');
  return n;
}

Type guard

function isValidThreshold(t: unknown): t is number {
  return typeof t === 'number' && !Number.isNaN(t) && t >= 0 && t <= 1;
}

Prevention

When it happens

Trigger: Calling memory.search('q', { threshold: '0.5' }) (string from JSON config or query param), threshold: NaN (result of a failed parseFloat), or threshold: null coerced oddly. Any value where typeof !== 'number' or Number.isNaN triggers it.

Common situations: Loading search options from JSON/YAML/env where everything arrives as a string ('0.5'), passing req.query.threshold straight from an HTTP handler, or computing threshold with parseFloat on unparsed input that yields NaN.

Related errors


AI-assisted analysis of mem0ai/mem0@001c235229 (2026-08-15). Data as JSON: /api/errors/780d73da35f1407b. Report an issue: GitHub.