What happened
With semantic memory disabled in the server config, deleting a project never completes: the session row stays in delete status forever, the project cannot be recreated (POST /projects returns 409), and a POST /memories on it raises SessionDeletedError, which is unhandled on that route and reaches the client as a dropped connection.
Config that reproduces it (event backend on SQLite, everything else default):
semantic_memory:
enabled: false
config_database: profile_storage
Flow: create a project, add a few episodic memories (types: ["episodic"]), POST /projects/delete (returns 204), then POST /projects with the same ids. Server log:
[ERROR] memmachine_server.main.memmachine - Failed to delete session manual_org/proj_a
...
File ".../main/memmachine.py", line 383, in _delete_session_episode_store
await self._cleanup_semantic_history(episode_ids)
File ".../main/memmachine.py", line 1178, in _cleanup_semantic_history
semantic_service = await self._resources.get_semantic_service()
...
memmachine_server.common.errors.ResourceNotReadyError: No database configured for semantic storage.
Line numbers as of 231ce171 (main): _delete_queued_session at packages/server/src/memmachine_server/main/memmachine.py:357 gates the semantic delete on self._conf.semantic_memory.enabled (line 361), but _delete_session_episode_store (line 369) calls _cleanup_semantic_history unconditionally (line 383), and that method (line 1168) requests the semantic service unconditionally (line 1177). With semantic memory disabled there is no semantic database, so SemanticManager.get_semantic_storage (common/resource_manager/semantic_manager.py:89) raises. The worker (_delete_session_worker, line 342) logs the exception and drops the job; nothing retries it. Because delete_session (line 582) returns early once the status is Deleted, a second delete request is a no-op, so the only way out is a server restart, which re-queues deleted sessions at boot (start, line 411) and fails the same way.
Note the partial state left behind: the deletion gathers the episode-store delete, the episodic-memory delete and (when enabled) the semantic delete concurrently, so by the time the episode-store branch raises, the episodic branch may already have dropped the vector collection and segment partition. The project is then neither deleted nor intact.
Expected
A deployment with semantic memory disabled must be able to delete projects. _cleanup_semantic_history should be skipped (or be a no-op) when semantic_memory.enabled is false, mirroring the guard _delete_queued_session already applies to the semantic delete itself. Independently, a failed deletion should not leave a session in a state that no API call can revisit.
Notes
Found by a manual end-to-end run against the server with the event backend on SQLite and again on PostgreSQL; the failure is dialect-independent. The same run also showed that a search on a project in delete status is still served from the process-local instance cache with 200 responses.
Investigated and written by Claude (Claude Code), filed from the account of the user who commissioned the investigation.
What happened
With semantic memory disabled in the server config, deleting a project never completes: the session row stays in
deletestatus forever, the project cannot be recreated (POST /projectsreturns 409), and aPOST /memorieson it raisesSessionDeletedError, which is unhandled on that route and reaches the client as a dropped connection.Config that reproduces it (event backend on SQLite, everything else default):
Flow: create a project, add a few episodic memories (
types: ["episodic"]),POST /projects/delete(returns 204), thenPOST /projectswith the same ids. Server log:Line numbers as of
231ce171(main):_delete_queued_sessionatpackages/server/src/memmachine_server/main/memmachine.py:357gates the semantic delete onself._conf.semantic_memory.enabled(line 361), but_delete_session_episode_store(line 369) calls_cleanup_semantic_historyunconditionally (line 383), and that method (line 1168) requests the semantic service unconditionally (line 1177). With semantic memory disabled there is no semantic database, soSemanticManager.get_semantic_storage(common/resource_manager/semantic_manager.py:89) raises. The worker (_delete_session_worker, line 342) logs the exception and drops the job; nothing retries it. Becausedelete_session(line 582) returns early once the status isDeleted, a second delete request is a no-op, so the only way out is a server restart, which re-queues deleted sessions at boot (start, line 411) and fails the same way.Note the partial state left behind: the deletion gathers the episode-store delete, the episodic-memory delete and (when enabled) the semantic delete concurrently, so by the time the episode-store branch raises, the episodic branch may already have dropped the vector collection and segment partition. The project is then neither deleted nor intact.
Expected
A deployment with semantic memory disabled must be able to delete projects.
_cleanup_semantic_historyshould be skipped (or be a no-op) whensemantic_memory.enabledis false, mirroring the guard_delete_queued_sessionalready applies to the semantic delete itself. Independently, a failed deletion should not leave a session in a state that no API call can revisit.Notes
Found by a manual end-to-end run against the server with the event backend on SQLite and again on PostgreSQL; the failure is dialect-independent. The same run also showed that a search on a project in
deletestatus is still served from the process-local instance cache with 200 responses.Investigated and written by Claude (Claude Code), filed from the account of the user who commissioned the investigation.