chroma-core/chroma · error · InvalidConfigurationError

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

Error message

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

What it means

Thrown by createCollectionConfigurationToJson (CollectionConfiguration.ts) when a CreateCollectionConfiguration passed to client.createCollection / getOrCreateCollection contains BOTH a truthy hnsw block and a truthy spann block. Chroma builds exactly one ANN index per collection at creation time, so specifying both HNSW and SPANN parameters is contradictory and is rejected client-side before any request is sent. It throws InvalidConfigurationError, a plain Error subclass exported from the same module.

Source

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

// --- 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,
): Record<string, any> {
  if (config.hnsw && config.spann) {
    throw new InvalidConfigurationError(
      "Cannot specify both 'hnsw' and 'spann' configurations during creation.",
    );
  }
  let hnswConfig = config.hnsw;
  let spannConfig = config.spann;
  let ef = config.embedding_function;
  let efConfig = serializeEmbeddingFunction(ef);

  // Basic validation/casting attempt
  if (hnswConfig && typeof hnswConfig !== "object") {
    throw new Error(
      "Invalid HNSW config provided in CreateCollectionConfiguration",
    );
  }
  if (spannConfig && typeof spannConfig !== "object") {
    throw new Error(
      "Invalid SPANN config provided in CreateCollectionConfiguration",
    );

View on GitHub (pinned to aecdd12c8a)

Solutions

  1. Delete either the hnsw or the spann key so the configuration contains only one index block.
  2. If migrating HNSW to SPANN, create a fresh collection with only the spann block and re-add data - index type is chosen at creation and cannot be switched by passing both.
  3. When building configuration dynamically, assert !cfg.hnsw || !cfg.spann before calling createCollection so you fail fast with your own error message.

Example fix

// before
await client.createCollection({
  name: 'docs',
  configuration: { hnsw: { space: 'cosine' }, spann: { search_nprobe: 10 } },
});

// after
await client.createCollection({
  name: 'docs',
  configuration: { spann: { search_nprobe: 10 } },
});
Defensive patterns

Strategy: validation

Validate before calling

function assertSingleIndexConfig(cfg: CreateCollectionConfiguration) {
  if (cfg.hnsw && cfg.spann) {
    throw new Error(
      `Pick one index type: hnsw=${JSON.stringify(cfg.hnsw)} spann=${JSON.stringify(cfg.spann)}`,
    );
  }
}
// before client.createCollection / getOrCreateCollection:
assertSingleIndexConfig(configuration);

Type guard

function hasSingleIndexConfig(
  cfg: CreateCollectionConfiguration,
): cfg is CreateCollectionConfiguration & { hnsw?: CreateHNSWConfiguration } {
  return !(cfg.hnsw && cfg.spann);
}

Try / catch

try {
  await client.createCollection({ name, configuration });
} catch (e) {
  if (e instanceof InvalidConfigurationError && /hnsw.*spann|spann.*hnsw/.test(e.message)) {
    // fix the config, exactly one index block allowed at creation
  }
  throw e;
}

Prevention

When it happens

Trigger: client.createCollection({ name: 'x', configuration: { hnsw: { space: 'cosine' }, spann: { search_nprobe: 10 } } }); the same applies to getOrCreateCollection and any other path that serializes a CreateCollectionConfiguration via createCollectionConfigurationToJson.

Common situations: Copy-pasting SPANN examples on top of an existing HNSW config while migrating; building the configuration object dynamically (Object.assign / spread of two partial configs) so both keys end up defined; toggling an experimental SPANN flag without removing the old hnsw block.

Related errors


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