chroma-core/chroma · error · ValueError

Trying to update SPANN config but schema has HNSW

Error message

Trying to update SPANN config but schema has HNSW

What it means

This ValueError inside update_schema_from_collection_configuration is raised when an update payload contains a spann block but the collection's vector_index.config.spann is None — i.e. the collection was created with the HNSW index. Mirroring error 356, modify cannot convert an HNSW collection to SPANN; only the existing index type's tunables may be updated.

Source

Thrown at chromadb/api/collection_configuration.py:875

            hnsw_config = vector_index.config.hnsw
            update_hnsw = configuration["hnsw"]

            # Only update fields that are present in the update
            if "ef_search" in update_hnsw:
                hnsw_config.ef_search = update_hnsw["ef_search"]
            if "num_threads" in update_hnsw:
                hnsw_config.num_threads = update_hnsw["num_threads"]
            if "batch_size" in update_hnsw:
                hnsw_config.batch_size = update_hnsw["batch_size"]
            if "sync_threshold" in update_hnsw:
                hnsw_config.sync_threshold = update_hnsw["sync_threshold"]
            if "resize_factor" in update_hnsw:
                hnsw_config.resize_factor = update_hnsw["resize_factor"]

        elif "spann" in configuration and configuration["spann"] is not None:
            # Update SPANN config
            if vector_index.config.spann is None:
                raise ValueError("Trying to update SPANN config but schema has HNSW")

            spann_config = vector_index.config.spann
            update_spann = configuration["spann"]

            # Only update fields that are present in the update
            if "search_nprobe" in update_spann:
                spann_config.search_nprobe = update_spann["search_nprobe"]
            if "ef_search" in update_spann:
                spann_config.ef_search = update_spann["ef_search"]

        # Update embedding function if present
        if (
            "embedding_function" in configuration
            and configuration["embedding_function"] is not None
        ):
            vector_index.config.embedding_function = configuration["embedding_function"]

    return schema

View on GitHub (pinned to aecdd12c8a)

Solutions

  1. For HNSW collections, send updates under 'hnsw' (ef_search, num_threads, batch_size, sync_threshold, resize_factor) instead of 'spann'
  2. To adopt SPANN, create a new collection with a spann configuration and re-ingest the data
  3. Branch update payloads on the collection's actual index type before calling modify

Example fix

// before
# collection created with default hnsw index
collection.modify(configuration={'spann': {'search_nprobe': 16}})  # ValueError

// after
collection.modify(configuration={'hnsw': {'ef_search': 128}})
Defensive patterns

Strategy: validation

Validate before calling

def index_type_of(collection) -> str:
    cfg = collection.configuration or {}
    return 'spann' if cfg.get('spann') is not None else 'hnsw'

update = {index_type_of(collection): {'ef_search': 100}}
collection.modify(configuration=update)

Type guard

def update_matches_index(update: dict, collection) -> bool:
    cfg = collection.configuration or {}
    if update.get('spann') is not None:
        return cfg.get('spann') is not None
    if update.get('hnsw') is not None:
        return cfg.get('hnsw') is not None
    return True

Try / catch

try:
    collection.modify(configuration=update)
except ValueError as e:
    if 'Trying to update SPANN config but schema has HNSW' in str(e):
        collection.modify(configuration={'hnsw': {'ef_search': 100}})
    else:
        raise

Prevention

When it happens

Trigger: Creating a collection with configuration={'hnsw': {...}} (the default) and then calling collection.modify(configuration={'spann': {'search_nprobe': 16}}). The guard fires on the first vector_index whose config.spann is None.

Common situations: Evaluating SPANN on existing HNSW-backed collections by flipping the config; shared tuning scripts that send spann blocks to every collection; CI pipelines applying uniform updates across heterogeneous collections.

Related errors


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