chroma-core/chroma · error · InvalidConfigurationError

Cannot specify both 'hnsw' and 'spann' configurations during

Error message

Cannot specify both 'hnsw' and 'spann' configurations during update.

What it means

Update-time twin of the creation error: updateCollectionConfigurationToJson throws InvalidConfigurationError when an UpdateCollectionConfiguration contains both hnsw and spann. This code path runs from collection.modify({ configuration }) (Collection.ts) before the updateCollection API call. A collection can only be tuned for the index type it was created with; sending both is rejected client-side.

Source

Thrown at clients/js/packages/chromadb-core/src/CollectionConfiguration.ts:307

    config.sync_threshold = jsonMap.sync_threshold;
  if ("resize_factor" in jsonMap) config.resize_factor = jsonMap.resize_factor;
  return config;
}

export function jsonToUpdateSpannConfiguration(
  jsonMap: Record<string, any>,
): UpdateSpannConfiguration {
  const config: UpdateSpannConfiguration = {};
  if ("search_nprobe" in jsonMap) config.search_nprobe = jsonMap.search_nprobe;
  if ("ef_search" in jsonMap) config.ef_search = jsonMap.ef_search;
  return config;
}

export function updateCollectionConfigurationToJson(
  config: UpdateCollectionConfiguration,
): Record<string, any> {
  if (config.hnsw && config.spann) {
    throw new InvalidConfigurationError(
      "Cannot specify both 'hnsw' and 'spann' configurations during update.",
    );
  }
  let hnswConfig = config.hnsw;
  let spannConfig = config.spann;
  let ef = config.embedding_function;
  let efConfig: Record<string, any> | null | undefined = undefined; // Initialize as undefined

  // Validate HNSW config if present
  if (hnswConfig) {
    if (typeof hnswConfig !== "object") {
      throw new Error(
        "Invalid HNSW config provided in UpdateCollectionConfiguration",
      );
    }
  }

  // Validate SPANN config if present

View on GitHub (pinned to aecdd12c8a)

Solutions

  1. Send only the block matching the collection's actual index type: hnsw for HNSW collections, spann for SPANN collections.
  2. Store which index type the collection was created with (or read it from collection.configuration) and build the update payload from that.
  3. Pre-check the payload: if (cfg.hnsw && cfg.spann) throw before calling modify.

Example fix

// before
await col.modify({
  configuration: { hnsw: { search_ef: 200 }, spann: { search_nprobe: 5 } },
});

// after (collection was created with HNSW)
await col.modify({ configuration: { hnsw: { search_ef: 200 } } });
Defensive patterns

Strategy: validation

Validate before calling

function assertUpdateSingleIndex(cfg: UpdateCollectionConfiguration) {
  if (cfg.hnsw && cfg.spann) {
    throw new Error('Update may target only the index type the collection was created with.');
  }
}
assertUpdateSingleIndex(configuration);
await col.modify({ configuration });

Type guard

function isCleanUpdateConfig(
  cfg: UpdateCollectionConfiguration,
): cfg is UpdateCollectionConfiguration {
  return !(cfg.hnsw && cfg.spann);
}

Try / catch

try {
  await col.modify({ configuration });
} catch (e) {
  if (e instanceof InvalidConfigurationError && e.message.includes('during update')) {
    // keep only the block matching the collection's created index type and retry
  }
  throw e;
}

Prevention

When it happens

Trigger: collection.modify({ configuration: { hnsw: { search_ef: 200 }, spann: { search_nprobe: 5 } } }); any client.updateCollection-style flow that funnels through loadApiUpdateCollectionConfigurationFromUpdateCollectionConfiguration.

Common situations: Reusing the create-time configuration object (which already has hnsw) and adding spann fields for tuning; copy-pasted update snippets mixing HNSW and SPANN parameters; generic 'update all index knobs' helper that always sets both blocks.

Related errors


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