headroomlabs-ai/headroom · error · ValueError
Saved index dimension {saved_dimension} does not match curre
Error message
Saved index dimension {saved_dimension} does not match current dimension {self._dimension} What it means
Raised by HNSWVectorIndex.load_index when the dimension recorded in the .meta file differs from the current index instance's dimension. A saved HNSW graph can only be loaded into an index configured for the same vector space, so this guard prevents mixing incompatible embeddings.
Source
Thrown at headroom/memory/adapters/hnsw.py:863
ValueError: If the saved dimension doesn't match.
"""
path = Path(path)
hnsw_path = path.with_suffix(".hnsw")
meta_path = path.with_suffix(".meta")
if not hnsw_path.exists():
raise FileNotFoundError(f"HNSW index not found: {hnsw_path}")
if not meta_path.exists():
raise FileNotFoundError(f"Metadata file not found: {meta_path}")
# Load metadata first to get parameters
with open(meta_path) as f:
meta_data = json.load(f)
# Verify dimension matches
saved_dimension = meta_data["dimension"]
if saved_dimension != self._dimension:
raise ValueError(
f"Saved index dimension {saved_dimension} does not match "
f"current dimension {self._dimension}"
)
with self._lock:
# Update parameters
self._max_elements = meta_data["max_elements"]
self._ef_construction = meta_data["ef_construction"]
self._m = meta_data["m"]
self._ef_search = meta_data["ef_search"]
# Restore bounding parameters (with defaults for backward compatibility)
self._max_entries = meta_data.get("max_entries")
self._eviction_batch_size = meta_data.get("eviction_batch_size", 100)
self._eviction_count = meta_data.get("eviction_count", 0)
# Create new index and load from file
self._index = hnswlib.Index(space="cosine", dim=self._dimension) # type: ignore[union-attr]View on GitHub (pinned to 322425c43b)
Solutions
- Construct the index with the dimension recorded in the .meta file (read meta_data['dimension'] first), or re-embed everything and save a new index.
- After changing embedders, version your index paths (e.g. index-miniLM.hnsw vs index-llm.hnsw) so old files are never loaded with new dimensions.
- Delete the stale files and rebuild from the memory store.
Example fix
// before
index = HNSWVectorIndex(dimension=384)
await index.load_index(path) # saved with 768
// after
meta = json.loads(path.with_suffix('.meta').read_text())
index = HNSWVectorIndex(dimension=meta['dimension'])
await index.load_index(path) Defensive patterns
Strategy: validation
Validate before calling
meta = json.loads(path.with_suffix('.meta').read_text())
index = HNSWVectorIndex(dimension=meta['dimension'])
await index.load_index(path) Try / catch
try:
await index.load_index(path)
except ValueError as e:
if "dimension" in str(e):
# stale index from another model: rebuild
await rebuild_index(index, memories) Prevention
- Version index filenames per embedding model.
- Always construct the index with the dimension from the saved metadata when loading.
When it happens
Trigger: Constructing HNSWVectorIndex(dimension=384) (or using a default) then loading a file saved with dimension=768; loading an index saved before switching embedding models.
Common situations: Embedding model upgrade without recreating the on-disk index; environment-specific defaults disagreeing; the constructor default silently used instead of the model's dimension.
Related errors
- HNSW index not found: {hnsw_path}
- Embedding dimension {embedding.shape[0]} does not match inde
- Query vector dimension {query_vector.shape[0]} does not matc
- Metadata file not found: {meta_path}
- deployment profile '{profile}' is corrupt ({path}): {e}
AI-assisted analysis of headroomlabs-ai/headroom@322425c43b (2026-08-15).
Data as JSON: /api/errors/55132b35e7a26f50.
Report an issue: GitHub.