chroma-core/chroma · error · Error

Multiple embedding functions provided. Please provide only o

Error message

Multiple embedding functions provided. Please provide only one.

What it means

Select.from_dict() (operator.py:1286) refuses to deserialize a Select from anything that is not a Python dict. Select controls which record keys a Search returns (documents, embeddings, scores, or metadata fields), and its dict form is the wire/JSON representation produced by Select.to_dict() (e.g. {"keys": ["#document", "#score"]}). Passing a string, list, or any non-mapping means the payload cannot be interpreted as a Select, so construction fails immediately with a TypeError. This is the first guard in a strict decode-validate pipeline — it exists to surface malformed search payloads at construction time instead of during query execution.

Source

Thrown at clients/js/packages/chromadb-core/src/ChromaClient.ts:244

   * ```
   */
  async createCollection({
    name,
    metadata,
    embeddingFunction = new DefaultEmbeddingFunction(),
    configuration,
  }: CreateCollectionParams): Promise<Collection> {
    await this.init();
    if (!configuration) {
      configuration = {};
    }
    if (
      hasEmbeddingFunctionConflict(
        embeddingFunction,
        configuration.embedding_function,
      )
    ) {
      throw new Error(
        "Multiple embedding functions provided. Please provide only one.",
      );
    }
    if (embeddingFunction && !configuration.embedding_function) {
      configuration.embedding_function = embeddingFunction;
    }
    let collectionConfiguration: Api.CollectionConfiguration | undefined =
      undefined;
    if (configuration) {
      collectionConfiguration =
        loadApiCollectionConfigurationFromCreateCollectionConfiguration(
          configuration,
        );
    }
    const newCollection = await this.api.createCollection(
      this.tenant,
      this.database,
      {

View on GitHub (pinned to aecdd12c8a)

Solutions

  1. Change the argument to the dict form: Select.from_dict({"keys": ["#document", "#score"]}) — the payload must be a mapping with a 'keys' entry.
  2. If you only have a list/set of key strings, pass it directly to Search(select=["#document", "#score"]); plan.py:151-153 wraps it into {"keys": list(select)} for you.
  3. If the payload comes from JSON text, decode it first: Select.from_dict(json.loads(payload_json)) so you hand it a dict, not a str.
  4. For programmatic construction prefer the typed/builder API: Select(keys={K.DOCUMENT, K.SCORE}) or Search().select(K.DOCUMENT, "title").

Example fix

// before
search = Search(select=Select.from_dict(["#document", "#score"]))  # TypeError: Expected dict for Select, got list

# after
search = Search(select={"keys": ["#document", "#score"]})
# or simply
search = Search(select=["#document", "#score"])
Defensive patterns

Strategy: type-guard

Validate before calling

from typing import Any, Dict
def is_select_payload(v: Any) -> bool:
    return isinstance(v, dict)

Type guard

def is_select_payload(v: Any) -> TypeGuard[Dict[str, Any]]:
    return isinstance(v, dict)

Try / catch

try:
    Select.from_dict(payload)
except TypeError as e:
    raise ValueError(f"Invalid select payload (expected mapping like {{'keys': [...]}}): {e}") from e

Prevention

When it happens

Trigger: Calling Search(select=<non-dict>) is mostly intercepted earlier by plan.py:147-157, so this fires mainly on direct calls: Select.from_dict(["#document"]) or Select.from_dict("#document") instead of {"keys": [...]}; rehydrating a Search plan with json.loads output that was double-encoded (a JSON string instead of an object); passing a YAML/JSON config value that parses to a list or None instead of a mapping; or reusing a Where/Rank-style payload dict for select.

Common situations: Hand-building query payloads from JSON config files or HTTP request bodies where select arrives as a bare list of strings; replaying serialized Search.to_dict() output after it was flattened or stringified; version migrations where the select parameter changed from a plain list to a Select object or {"keys": ...} dict; copy-pasting from docs that show Search().select(K.DOCUMENT) (builder form) while passing the same value into the Search(select=...) constructor.

Related errors


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