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
- Change the argument to the dict form: Select.from_dict({"keys": ["#document", "#score"]}) — the payload must be a mapping with a 'keys' entry.
- 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.
- 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.
- 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
- Build select payloads only via Select(...).to_dict() or {'keys': [...]} literals.
- json.loads raw text before decoding; never forward undecoded strings.
- For plain key lists pass Search(select=["#document"]) and let plan.py wrap it.
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
- Unauthorized
- Failed to connect to chromadb. Make sure your server is runn
- Invalid JSON string for collection configuration
- Expected dict for Limit, got {type(data).__name__}
- Bad request to ${input} with status: ${resp.statusText}
AI-assisted analysis of chroma-core/chroma@aecdd12c8a (2026-08-16).
Data as JSON: /api/errors/f908742831eaa91d.
Report an issue: GitHub.