headroomlabs-ai/headroom · error · ValueError
Memory {memory.id} has no embedding
Error message
Memory {memory.id} has no embedding What it means
Raised by SQLiteVectorIndex._prepare_memory_for_index when a Memory passed for indexing has embedding None. Like the HNSW backend, the sqlite-vec index only stores pre-computed vectors and expects embedding to be produced by an external Embedder first.
Source
Thrown at headroom/memory/adapters/sqlite_vector.py:296
conn: sqlite3.Connection,
memory_ids: list[str],
) -> dict[str, int]:
"""Fetch rowids for the given memory IDs."""
rowids: dict[str, int] = {}
for chunk in self._chunked(memory_ids):
placeholders = ", ".join("?" for _ in chunk)
rows = conn.execute(
f"SELECT rowid, memory_id FROM vec_metadata WHERE memory_id IN ({placeholders})",
chunk,
).fetchall()
for row in rows:
rowids[str(row["memory_id"])] = int(row["rowid"])
return rowids
def _prepare_memory_for_index(self, memory: Memory) -> tuple[np.ndarray, VectorMetadata]:
"""Validate a memory and prepare it for indexing."""
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}"
)
return embedding, VectorMetadata.from_memory(memory)
def _metadata_insert_params(self, memory_id: str, metadata: VectorMetadata) -> tuple[Any, ...]:
"""Build INSERT parameters for vector metadata."""
return (
memory_id,
metadata.user_id,
metadata.session_id,
metadata.agent_id,
metadata.importance,View on GitHub (pinned to 322425c43b)
Solutions
- Embed the memory before indexing: memory.embedding = await embedder.embed(memory.content).
- Filter or re-queue memories with None embeddings in batch indexing loops.
- Make embedding mandatory in your ingest path so un-embedded memories cannot reach the index.
Example fix
// before
await index.index_memory(memory) # embedding is None
// after
if memory.embedding is None:
memory.embedding = await embedder.embed(memory.content)
await index.index_memory(memory) Defensive patterns
Strategy: validation
Validate before calling
if memory.embedding is None:
memory.embedding = await embedder.embed(memory.content)
await index.index_memory(memory) Type guard
def has_embedding(m: Memory) -> bool:
return m.embedding is not None Try / catch
try:
await index.index_memory(memory)
except ValueError as e:
if "no embedding" in str(e):
memory.embedding = await embedder.embed(memory.content)
await index.index_memory(memory)
else:
raise Prevention
- Enforce embed-then-index ordering in the ingest pipeline.
- Skip and log records with missing embeddings in batch jobs instead of aborting.
When it happens
Trigger: Calling index_memory/add with a memory that skipped the embedding step; embeddings computed asynchronously and not awaited; memories loaded from storage where the embedding column was null.
Common situations: Pipeline order bugs (index before embed); optional embeddings in the schema left unset; batch jobs where some records failed embedding earlier.
Related errors
- Memory {memory.id} has no embedding
- Embedding dimension {embedding.shape[0]} does not match inde
- save_path must be provided when auto_save is True
- Embedding dimension {embedding.shape[0]} does not match inde
- query_text provided but SQLiteVectorIndex does not embed tex
AI-assisted analysis of headroomlabs-ai/headroom@322425c43b (2026-08-15).
Data as JSON: /api/errors/605e908dae30426f.
Report an issue: GitHub.