chroma-core/chroma · error · Error
Could not serialize collection configuration
Error message
Could not serialize collection configuration
What it means
GroupBy.from_dict() (operator.py:1526-1527) raises ValueError when the 'keys' list of a group_by dict is empty. Grouping requires at least one metadata field to partition results on — an empty keys list defines zero grouping dimensions, which is indistinguishable from 'no grouping', and Chroma requires you to say that differently: pass {} (which returns the default GroupBy, operator.py:1514-1515) or omit group_by entirely. The empty-list case is treated as a malformed non-empty payload, not as the no-grouping request.
Source
Thrown at clients/js/packages/chromadb-core/src/CollectionConfiguration.ts:230
// not necessarily to retrieving/displaying the existing config.
return {
hnsw: hnswConfig,
spann: spannConfig,
embedding_function: efConfig,
};
}
export function collectionConfigurationToJsonStr(
config: CollectionConfiguration,
): string {
try {
const jsonObj = collectionConfigurationToJson(config);
return JSON.stringify(jsonObj);
} catch (e: any) {
if (e instanceof InvalidConfigurationError) throw e;
console.error("Error serializing collection configuration to JSON:", e);
throw new Error("Could not serialize collection configuration");
}
}
// --- Create Configuration Helpers ---
export function loadApiCollectionConfigurationFromCreateCollectionConfiguration(
config: CreateCollectionConfiguration,
): Api.CollectionConfiguration {
// Cast needed because the generated Api type might not be perfectly aligned
// with our internal Create* types, but the structure should match after JSON conversion.
return createCollectionConfigurationToJson(
config,
) as Api.CollectionConfiguration;
}
// TODO: make warnings prettier and add link to migration docs
export function createCollectionConfigurationToJson(
config: CreateCollectionConfiguration,View on GitHub (pinned to aecdd12c8a)
Solutions
- If no grouping is wanted, omit group_by or pass {} — never {"keys": [], ...}.
- Gate payload construction: build group_by only when the field list is non-empty: group_by = {"keys": fields, "aggregate": agg} if fields else None.
- Validate at your API boundary: reject empty group-field lists or convert them to 'no grouping'.
- Ensure YAML/JSON templates never materialize keys: [] alongside an aggregate.
Example fix
// before
group_by = {"keys": [], "aggregate": {"$min_k": {"keys": ["#score"], "k": 3}}}
# ValueError: GroupBy keys cannot be empty
# after
group_by = None # or {} — both mean no grouping
search = Search(group_by=group_by, ...) Defensive patterns
Strategy: validation
Validate before calling
def groupby_keys_nonempty_or_absent(payload: dict) -> bool:
return "keys" not in payload or (isinstance(payload["keys"], (list, tuple)) and len(payload["keys"]) > 0) Type guard
def is_valid_groupby(v: Any) -> TypeGuard[Dict[str, Any]]:
if not isinstance(v, dict):
return False
if not v:
return True
ks = v.get("keys")
return (
isinstance(ks, (list, tuple))
and len(ks) > 0
and all(isinstance(k, str) for k in ks)
and isinstance(v.get("aggregate"), dict)
and len(v["aggregate"]) == 1
) Try / catch
try:
GroupBy.from_dict(payload)
except ValueError as e:
if "keys cannot be empty" in str(e):
return None # reinterpret as no grouping
raise Prevention
- No grouping = omit group_by or {}; never {'keys': [], ...}.
- Builders: emit group_by only when the field list is non-empty (group_by = {...} if fields else None).
- Treat empty group-field selections from UIs as 'no grouping', not empty arrays forwarded downstream.
When it happens
Trigger: {"keys": [], "aggregate": {...}} — explicit empty list; a computed field list that evaluated to [] (user supplied no group fields, but the builder still emitted the dict); YAML where all keys entries were commented out; template merging that stripped every grouping field yet kept aggregate.
Common situations: APIs that accept a list of group fields and build group_by unconditionally — emitting {"keys": [], "aggregate": ...} for empty input instead of {}; optional config sections that default to empty lists; frontends sending empty arrays for unset multi-select controls.
Related errors
- ${respBody?.message}
- No API key provided
- Invalid HNSW config provided
- Bad request to ${input} with status: ${resp.statusText}
- Unauthorized
AI-assisted analysis of chroma-core/chroma@aecdd12c8a (2026-08-16).
Data as JSON: /api/errors/0a7819110b704d4a.
Report an issue: GitHub.