Skip to content

bug(memory): entity embeddings never stored in Qdrant — EntityResolver built without provider in extract_and_store #1829

@bug-ops

Description

@bug-ops

Summary

EntityResolver in extract_and_store() (crates/zeph-memory/src/semantic/graph.rs) is built with .with_embedding_store(emb) but without .with_provider(&provider). Because provider is moved into GraphExtractor::new(provider, ...) at line 281, it is unavailable when the resolver is constructed.

Root cause

resolve_with_embedding_store() in resolver.rs has an early guard:

let (Some(emb_store), Some(provider)) = (self.embedding_store, self.provider) else {
    return Ok(None);
};

Since self.provider is always None in production, store_entity_embedding() is never called → the zeph_graph_entities Qdrant collection is never populated → link_memory_notes() always receives Collection 'zeph_graph_entities' doesn't exist! errors → entities_processed=0, edges_created=0 on every turn.

Reproduction

Run with graph memory + Qdrant + orchestrator (embed = ollama). After two turns with related entities, the graph DB shows extracted entities in SQLite but:

  • Qdrant has no zeph_graph_entities collection
  • All note_linking: search failed with Collection not found
  • note linking completed entities_processed=0 edges_created=0

Observed in live session with config vector_backend = "qdrant", note_linking.enabled = true, orchestrator embed = "ollama".

Fix

Clone provider before passing to GraphExtractor::new(), then pass the clone to .with_provider() on the resolver:

let resolver = if let Some(ref emb) = embedding_store {
    EntityResolver::new(&store)
        .with_embedding_store(emb)
        .with_provider(&provider)   // ← add this
} else {
    EntityResolver::new(&store)
};

Requires: provider.clone() passed to GraphExtractor::new() so provider is still available at the resolver construction site.

Impact

A-MEM note linking (similar_to edges) has never worked in production since the feature was introduced. PR #1827 fixed a separate issue (embedding store not passed to link_memory_notes), but this root cause was not caught because unit tests use MockProvider passed via .with_provider() directly — they bypass extract_and_store() entirely.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingmemoryzeph-memory crate (SQLite)

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions