headroomlabs-ai/headroom · error · ValueError

Embedding dimension {embedding.shape[0]} does not match inde

Error message

Embedding dimension {embedding.shape[0]} does not match index dimension {self._dimension}

What it means

Raised by HNSWVectorIndex.add_memory when the supplied embedding's length differs from the dimension the index was constructed with (self._dimension). HNSW graphs have a fixed vector size at creation, so any vector of a different length is rejected before insertion.

Source

Thrown at headroom/memory/adapters/hnsw.py:338

    async def index(self, memory: Memory) -> None:
        """Index a memory's embedding for similarity search.

        The memory must have an embedding set. If max_entries is set and
        the limit is reached, low-importance entries are evicted.

        Args:
            memory: The memory to index.

        Raises:
            ValueError: If the memory has no embedding or wrong dimension.
        """
        if memory.embedding is None:
            raise ValueError(f"Memory {memory.id} has no embedding")

        embedding = np.asarray(memory.embedding, dtype=np.float32)
        if embedding.shape[0] != self._dimension:
            raise ValueError(
                f"Embedding dimension {embedding.shape[0]} does not match "
                f"index dimension {self._dimension}"
            )

        with self._lock:
            # Check if already indexed - update if so
            if memory.id in self._memory_to_hnsw:
                await self._update_embedding_internal(memory.id, embedding)
                # Update metadata
                self._metadata[memory.id] = IndexedMemoryMetadata.from_memory(memory)
            else:
                # Evict if at capacity (before adding new entry)
                if self._max_entries is not None:
                    current_size = len(self._memory_to_hnsw)
                    if current_size >= self._max_entries:
                        self._evict_entries(self._eviction_batch_size)

                # Resize HNSW index if needed (separate from entry limit)

View on GitHub (pinned to 322425c43b)

Solutions

  1. Print/inspect embedding.shape[0] and the index dimension, then recreate the index with dimension matching your Embedder output.
  2. If the model changed, rebuild the index from scratch (re-embed all memories) — you cannot mix dimensions in HNSW.
  3. Centralize the dimension: derive index dimension from embedder.dimension instead of a hardcoded literal.

Example fix

// before
index = HNSWVectorIndex(dimension=384)
await index.add_memory(memory)  # embedder returns 768-dim

// after
index = HNSWVectorIndex(dimension=embedder.dimension)
await index.add_memory(memory)
Defensive patterns

Strategy: validation

Validate before calling

dim = np.asarray(memory.embedding).shape[0]
if dim != index.dimension:
    raise RuntimeError(f"embedder dim {dim} != index dim {index.dimension}")

Prevention

When it happens

Trigger: Index created with dimension=384 but the Embedder produces 768-dim vectors (e.g. switching MiniLM to a larger model); mixing embeddings from different providers in one index; loading an index saved with another dimension.

Common situations: Changing embedding model without rebuilding the index; copy-pasting a dimension constant that no longer matches the model; using a default dimension while embedding with a non-default model.

Related errors


AI-assisted analysis of headroomlabs-ai/headroom@322425c43b (2026-08-15). Data as JSON: /api/errors/e28f5c4062d504a0. Report an issue: GitHub.