Skip to content

bug: Soul Writer uses asyncio.Lock across event loop boundaries #34

@G9000

Description

@G9000

Summary

soul_writer.py:20-26 stores asyncio.Lock objects in a plain dict[int, asyncio.Lock]. run_soul_writer is called from:

  • Pre-turn check (main event loop)
  • Post-compaction (main event loop)
  • on_thread_close via eager_consolidation (background task, potentially different loop)
  • inactivity_sweep (background task)

An asyncio.Lock created on one event loop cannot be acquired on another — raises RuntimeError on Python 3.10+.

Secondary Issue

_user_locks dict grows without bound (no eviction).

Fix

Replace asyncio.Lock with threading.Lock since the inner pipeline (_run_soul_writer_inner) is synchronous and runs via asyncio.to_thread. Alternatively, ensure all callers share the same event loop and add a size cap.

Files

  • apps/server/src/anima_server/services/agent/soul_writer.py:20-26, 56-64

Severity

High — crash on cross-loop lock acquisition.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions