Skip to content

[Bug]: Semantic session manager and semantic service each build their own config cache, so set type deletes and registrations do not reach ingestion #1730

Description

@edwinyyyu

Describe the bug

The semantic session manager and the semantic service each get their own CachingSemanticConfigStorage over the same config database. Set type writes go through the session manager's instance, but set configs, which carry the categories a set inherits from its set type, are read and cached through the service's instance. Writes through one instance never invalidate the other. So after a set type is deleted, ingestion keeps extracting with its deleted categories; after a set is registered to a new set type, ingestion does not see that type's categories. Both last until a later write through the service's instance happens to clear its set config cache (a category, tag or category template change), or until the process restarts.

As of 82b6c6f58 (main), paths under packages/server/src/memmachine_server/:

  • common/resource_manager/semantic_manager.py:175-194: get_semantic_config_storage builds a new SemanticConfigStorageSqlAlchemy, wrapped in a new CachingSemanticConfigStorage when with_config_cache is set (the default, common/configuration/__init__.py:154-157), on every call. It is called once for the service (:242) and again for the session manager (:268).
  • semantic_memory/config_store/caching_semantic_config_storage.py:20-25 states that "Cache entries are invalidated on write operations"; each write invalidates only its own instance's dictionaries (for example delete_set_type_id, :336-346, and register_set_id_set_type, :97-117).
  • The session manager writes set types through its instance: add_set_type_id (semantic_memory/semantic_session_manager.py:484, :503), delete_set_type_id (:516), register_set_id_set_type (:388, :646).
  • The service reads set configs through the other instance: _set_id_resource (semantic_memory/semantic_memory.py:505), which supplies ingestion's categories and get_set_id_category_names, and _set_ids_embedders (:476). A set config includes the categories inherited from the set's registered set type (semantic_memory/config_store/config_store_sqlalchemy.py:317-337).

Steps to reproduce

Build the real SemanticResourceManager (SQLite config and feature databases, mock embedder and language model) and call the public session manager methods behind /memories/semantic/set_type, /memories/semantic/set_type/delete and /memories/semantic/category/template:

session_manager = await manager.get_semantic_session_manager()
service = await manager.get_semantic_service()

type_1 = await session_manager.create_set_type(session_data=session, metadata_tags=["topic"])
await session_manager.add_category_template(set_type_id=type_1, category_name="travel_plans", prompt="p", description=None)
set_id = await session_manager.get_set_id(session_data=session, set_metadata_keys=["topic"], set_metadata={"topic": "x"})

await session_manager.delete_set_type(set_type_id=type_1)

type_2 = await session_manager.create_set_type(session_data=session, metadata_tags=["topic"])
await session_manager.add_category_template(set_type_id=type_2, category_name="budget", prompt="p", description=None)
await session_manager.get_set_id_category_names(set_id=set_id)  # any read, e.g. an ingestion pass
await session_manager.get_set_id(session_data=session, set_metadata_keys=["topic"], set_metadata={"topic": "x"})

Measured, comparing get_set_id_category_names (served) with an uncached SemanticConfigStorageSqlAlchemy read of the same set (stored):

service and session manager share one config store: False
before delete      (served, stored): (['travel_plans'], ['travel_plans'])
after delete       (served, stored): (['travel_plans'], [])
after re-register  (served, stored): ([], ['budget'])

Not run: a full server with background ingestion. Ingestion reads the same _set_id_resource on every pass (semantic_memory/semantic_ingestion.py:123).

Expected behavior

One process has one semantic config cache. SemanticResourceManager builds the config storage once and gives the same instance to the service and the session manager, so every write invalidates the cache that serves later reads, and a set's categories reflect its current set type.

Environment

  • MemMachine: main at 82b6c6f58
  • Python 3.14.3, SQLite 3.50.4, macOS
  • semantic_memory.with_config_cache: true (the default)

🤖 Written by Claude Code (Claude Opus 5.5) on behalf of @edwinyyyu.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions