chroma-core/chroma · error · ChromaValueError

Expected operand for ${operator} to be a non empty string, b

Error message

Expected operand for ${operator} to be a non empty string, but got ${operand}

What it means

Intended meaning: the operand of $contains/$not_contains/$regex/$not_regex must be a non-empty string. In this client version the guard is transposed — it compares `operand` against operator names and tests typeof of `operator` (utils.ts:696-702) — so with an ordinary single-key clause it never fires; a non-string or empty-string operand passes through and fails server-side instead. The local throw is only reachable via degenerate input such as { '': '$contains' } (empty-string key whose value equals an operator name).

Source

Thrown at clients/new-js/packages/chromadb/src/utils.ts:703

    }

    if (operand.length <= 1) {
      throw new ChromaValueError(
        `Expected 'whereDocument' operand for ${operator} to be a list with at least two 'whereDocument' expressions`,
      );
    }

    operand.forEach((item) => validateWhereDocument(item));
  }

  if (
    (operand === "$contains" ||
      operand === "$not_contains" ||
      operand === "$regex" ||
      operand === "$not_regex") &&
    (typeof (operator as any) !== "string" || operator.length === 0)
  ) {
    throw new ChromaValueError(
      `Expected operand for ${operator} to be a non empty string, but got ${operand}`,
    );
  }
};

/**
 * Validates include fields for query operations.
 * @param options - Validation options
 * @param options.include - Array of fields to include in results
 * @param options.exclude - Optional array of fields that should not be included
 * @throws ChromaValueError if include fields are invalid
 */
export const validateInclude = ({
  include,
  exclude,
}: {
  include: Include[];
  exclude?: Include[];

View on GitHub (pinned to aecdd12c8a)

Solutions

  1. Validate operands yourself before the call: non-empty string for $contains/$not_contains/$regex/$not_regex
  2. Reject or default empty search terms before building the filter
  3. Upgrade the chromadb JS package, whose utils.ts operand validation is actively maintained

Example fix

// before
whereDocument: { $contains: term } // term can be ''

// after
if (typeof term !== 'string' || term.length === 0) throw new Error('term must be a non-empty string');
whereDocument: { $contains: term }
Defensive patterns

Strategy: validation

Validate before calling

const STRING_OPERATORS = ['$contains', '$not_contains', '$regex', '$not_regex'];
function validateOperands(w: Record<string, unknown>): void {
  const [op, val] = Object.entries(w)[0];
  if (STRING_OPERATORS.includes(op) && (typeof val !== 'string' || val.length === 0)) {
    throw new TypeError(`operand for ${op} must be a non-empty string`);
  }
}

Type guard

const hasNonEmptyStringOperand = (
  w: unknown
): w is { $contains: string } | { $not_contains: string } | { $regex: string } | { $not_regex: string } => {
  if (typeof w !== 'object' || w === null) return false;
  const [op, val] = Object.entries(w)[0];
  return ['$contains', '$not_contains', '$regex', '$not_regex'].includes(op) &&
    typeof val === 'string' && val.length > 0;
};

Try / catch

try {
  await col.get({ whereDocument: { $contains: term } });
} catch (e) {
  // this client-side guard is transposed in utils.ts, so expect the failure from the server instead:
  if (e instanceof Error && /contains|operand/i.test(e.message)) {
    // surface 'search term must be a non-empty string' to the caller
  } else throw e;
}

Prevention

When it happens

Trigger: Effectively only { '': '$contains' }-shaped objects trip the local throw. The intended cases — { $contains: '' } or { $regex: 123 } — are not caught here and surface later as a server error with a different message.

Common situations: Empty-string search terms from unvalidated user input; numeric regex patterns passed straight from JSON; noticing after an upgrade that operand type errors now come from the server rather than the client.

Related errors


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