{"record":{"id":"8a4d7d9b0a3b8bc2","repo":"chroma-core/chroma","slug":"hnsw-and-spann-cannot-both-be-provided","errorCode":null,"errorMessage":"hnsw and spann cannot both be provided","messagePattern":"hnsw and spann cannot both be provided","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"chromadb/api/collection_configuration.py","lineNumber":66,"sourceCode":"    embedding_function: Optional[EmbeddingFunction]  # type: ignore\n\n\ndef load_collection_configuration_from_json_str(\n    config_json_str: str,\n) -> CollectionConfiguration:\n    config_json_map = json.loads(config_json_str)\n    return load_collection_configuration_from_json(config_json_map)\n\n\n# TODO: make warnings prettier and add link to migration docs\ndef load_collection_configuration_from_json(\n    config_json_map: Dict[str, Any]\n) -> CollectionConfiguration:\n    if (\n        config_json_map.get(\"spann\") is not None\n        and config_json_map.get(\"hnsw\") is not None\n    ):\n        raise ValueError(\"hnsw and spann cannot both be provided\")\n\n    hnsw_config = None\n    spann_config = None\n    ef_config = None\n\n    # Process vector index configuration (HNSW or SPANN)\n    if config_json_map.get(\"hnsw\") is not None:\n        hnsw_config = cast(HNSWConfiguration, config_json_map[\"hnsw\"])\n    if config_json_map.get(\"spann\") is not None:\n        spann_config = cast(SpannConfiguration, config_json_map[\"spann\"])\n\n    # Process embedding function configuration\n    if config_json_map.get(\"embedding_function\") is not None:\n        ef_config = config_json_map[\"embedding_function\"]\n        if ef_config[\"type\"] == \"legacy\":\n            warnings.warn(\n                \"legacy embedding function config\",\n                DeprecationWarning,","sourceCodeStart":48,"sourceCodeEnd":84,"githubUrl":"https://github.com/chroma-core/chroma/blob/aecdd12c8a891610db8653630b066b32ceb678b5/chromadb/api/collection_configuration.py#L48-L84","documentation":"load_collection_configuration_from_json() refuses a configuration map in which both the 'spann' and 'hnsw' keys are non-null. A Chroma collection must use exactly one vector index backend, so a persisted or hand-built configuration naming both is rejected when the collection is loaded (get_collection) or when the JSON is parsed.","triggerScenarios":"get_collection() on a collection whose stored configuration JSON contains both 'hnsw' and 'spann' (corrupt or manually edited data); building the configuration dict yourself with both keys; copying/modifying persisted SQLite rows when experimenting with SPANN migrations.","commonSituations":"Attempting an HNSW→SPANN migration by editing stored config; bugs in scripts that merge configuration JSONs; testing the newer SPANN index against existing HNSW collections.","solutions":["Recreate the collection specifying only one index type in its configuration.","If you control the dict, delete one of the two keys before passing it.","Repair the stored configuration (remove the stray key from the collection's config JSON in the backing store) — back up data first.","Report upstream if the stored both-keys state was produced by Chroma itself."],"exampleFix":"# before\nconfig_json = {\"hnsw\": {\"space\": \"l2\"}, \"spann\": {\"search_nprobe\": 16}}\nload_collection_configuration_from_json(config_json)  # ValueError\n\n# after\nconfig_json = {\"hnsw\": {\"space\": \"l2\"}}\nload_collection_configuration_from_json(config_json)","handlingStrategy":"validation","validationCode":"def single_index_config(config: dict) -> dict:\n    if config.get(\"hnsw\") is not None and config.get(\"spann\") is not None:\n        raise ValueError(\"pick one: hnsw or spann\")\n    return config\n\nconfig = single_index_config({\"hnsw\": {\"space\": \"l2\"}, \"spann\": None})  # ok","typeGuard":null,"tryCatchPattern":"try:\n    col = client.get_collection(\"docs\")\nexcept ValueError as e:\n    if \"cannot both be provided\" in str(e):\n        # stored config is corrupt: recreate the collection with one index type\n        ...\n    raise","preventionTips":["Never hand-edit persisted collection configuration JSON.","When migrating index types, recreate the collection instead of merging configs.","Validate configuration dicts for exactly one non-null index key before create."],"tags":["chroma","collection-configuration","hnsw","spann","vector-index"],"backgroundTag":"conflicting-configuration","analyzedSha":"aecdd12c8a891610db8653630b066b32ceb678b5","analyzedAt":"2026-08-16T21:53:27.228Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}