{"record":{"id":"f76ca756ffd4032b","repo":"chroma-core/chroma","slug":"invalid-json-string-for-collection-configuration","errorCode":null,"errorMessage":"Invalid JSON string for collection configuration","messagePattern":"Invalid JSON string for collection configuration","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"clients/js/packages/chromadb-core/src/CollectionConfiguration.ts","lineNumber":186,"sourceCode":"    deserializeEmbeddingFunction(jsonMap.embedding_function);\n\n  return {\n    hnsw: hnswConfig,\n    spann: spannConfig,\n    embedding_function: embeddingFunction,\n  };\n}\n\nexport function loadCollectionConfigurationFromJsonStr(\n  jsonStr: string,\n): CollectionConfiguration {\n  try {\n    const jsonMap = JSON.parse(jsonStr);\n    return loadCollectionConfigurationFromJson(jsonMap);\n  } catch (e: any) {\n    if (e instanceof InvalidConfigurationError) throw e;\n    console.error(\"Error parsing JSON string for collection configuration:\", e);\n    throw new Error(\"Invalid JSON string for collection configuration\");\n  }\n}\n\nexport function collectionConfigurationToJson(\n  config: CollectionConfiguration,\n): Record<string, any> {\n  if (config.hnsw && config.spann) {\n    throw new InvalidConfigurationError(\n      \"Cannot specify both 'hnsw' and 'spann' configurations.\",\n    );\n  }\n  let hnswConfig = config.hnsw;\n  let spannConfig = config.spann;\n  let ef = config.embedding_function;\n  let efConfig = serializeEmbeddingFunction(ef);\n\n  // Basic validation/casting attempt (already done in create/update, but maybe check types?)\n  if (hnswConfig && typeof hnswConfig !== \"object\") {","sourceCodeStart":168,"sourceCodeEnd":204,"githubUrl":"https://github.com/chroma-core/chroma/blob/aecdd12c8a891610db8653630b066b32ceb678b5/clients/js/packages/chromadb-core/src/CollectionConfiguration.ts#L168-L204","documentation":"GroupBy.from_dict() (operator.py:1514-1515) raises TypeError when the group_by payload is not a dict. GroupBy's dict form is either {} (no grouping) or {\"keys\": [...], \"aggregate\": {...}} — the shape emitted by GroupBy.to_dict() (operator.py:1508-1510). A list of field names, a string, or None cannot be decoded, so construction aborts. In the Search constructor (plan.py:123-124) a dict group_by is routed here while a GroupBy instance passes through and anything else fails earlier — so this error typically comes from calling GroupBy.from_dict directly.","triggerScenarios":"GroupBy.from_dict(\"category\") or GroupBy.from_dict([\"category\"]) — a bare field or list instead of the wrapped mapping; Search(group_by=[\"category\"]) is caught by plan.py:125-128 with its own message, but Search(group_by={...}-shaped JSON string) reaches json boundary issues; YAML config where the group_by section lost its mapping structure; forwarding a string field name from an API query parameter.","commonSituations":"Users assuming group_by takes a field name or list like SQL GROUP BY; config files where indentation collapse turned the mapping into a scalar; REST handlers forwarding raw query-param strings into the search payload; replaying Search.to_dict() output in which group_by was stringified.","solutions":["Wrap the fields in the mapping form: {\"keys\": [\"category\"], \"aggregate\": {\"$min_k\": {\"keys\": [\"#score\"], \"k\": 3}}}.","Use {} (or omit group_by) when no grouping is wanted.","Prefer the typed API for readability: GroupBy(keys=[\"category\"], aggregate=MinK(keys=K.SCORE, k=3)).","json.loads any JSON text before passing it as group_by."],"exampleFix":"// before\nsearch = Search(group_by=[\"category\"])   # rejected earlier by plan.py; direct form:\ngb = GroupBy.from_dict([\"category\"])      # TypeError: Expected dict for GroupBy, got list\n\n# after\ngb = GroupBy.from_dict({\"keys\": [\"category\"], \"aggregate\": {\"$min_k\": {\"keys\": [\"#score\"], \"k\": 3}}})","handlingStrategy":"type-guard","validationCode":"def is_groupby_payload(v: Any) -> bool:\n    return isinstance(v, dict)","typeGuard":"def is_groupby_dict(v: Any) -> TypeGuard[Dict[str, Any]]:\n    return isinstance(v, dict)","tryCatchPattern":"try:\n    GroupBy.from_dict(payload)\nexcept TypeError as e:\n    raise ValueError(\n        f\"group_by must be {{}}, or {{'keys': [...], 'aggregate': {{...}}}} — got {payload!r}\"\n    ) from e","preventionTips":["Wrap group fields in the mapping form; a bare list/string is never accepted.","Omit group_by (or {}) when no grouping is intended.","Prefer typed construction: GroupBy(keys=['category'], aggregate=MinK(...))."],"tags":["chromadb","groupby","typeerror","deserialization"],"backgroundTag":"dict-schema-validation-failed","analyzedSha":"aecdd12c8a891610db8653630b066b32ceb678b5","analyzedAt":"2026-08-16T21:53:27.228Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}