You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
basic-memory schema validate prints its result then hangs instead of exiting (Python 3.13) #1345
basic-memory schema validate does all of its work, prints its result, and then
never exits. The process has to be killed.
$ basic-memory schema validate --project <name> --json --local
{
"error": "No schemas defined in this project"
}
# ...and then it hangs, indefinitely
The output is complete and correct — only the exit is stuck.
What I expected
The command prints its result and exits 0.
Reproducing it
This reproduces reliably in a clean, isolated environment: a fresh uv-installed 0.23.2 with its own HOME, XDG_CONFIG_HOME, XDG_DATA_HOME
and BASIC_MEMORY_CONFIG_DIR, on CPython 3.13.15 (macOS, Apple Silicon).
A/B in that environment, toggling only the def/async def keyword on get_app_config and changing nothing else:
WITHOUT FIX (sync get_app_config): HUNG after 90s
WITH FIX (async get_app_config): exit=0 in 8.24s
A caveat that cost me time, and may cost yours: I could not reproduce this
when running against my normal, already-warm user environment — there the same
command exits in ~2.5s either way. If it does not reproduce for you on the first
try, use a clean isolated config/home rather than concluding it is not there.
Cause, as far as I can tell
get_app_config in src/basic_memory/deps/config.py is a sync FastAPI
dependency. FastAPI resolves sync dependencies in AnyIO's worker-thread pool,
and those workers are non-daemon and stay parked on queue.Queue.get after the
request so they can be reused.
The CLI drives the app under asyncio.run through httpx.ASGITransport, with
no blocking portal to join that pool on the way out. So asyncio.run returns
with a live non-daemon thread, and threading._shutdown waits on a thread
nothing will ever wake.
run_with_cleanup in cli/commands/command_utils.py drains pending
materializations, background tasks and the DB, but it does not join the AnyIO
worker pool, so it does not cover this.
Directly observable, independent of the CLI — a minimal FastAPI app with one
route depending on AppConfigDep, driven over ASGITransport:
WITH FIX: workers before = 0 / status 200 / workers after = 0 []
WITHOUT FIX: workers before = 0 / status 200 / workers after = 1 ['AnyIO worker thread']
This is not limited to schema validate — any CLI or MCP command that drives
the API through the in-process ASGI transport and touches AppConfigDep is
exposed. schema validate is just where it is easiest to see, because that
command does little else.
Fixed by #1349 (on main now, so it's in the next .dev build on PyPI and will ship in the next patch release). Root cause was nest_asyncio, applied for Alembic on Python < 3.14, swallowing the callback anyio uses to stop its worker thread after a sync FastAPI dependency ran — details in the PR. Thanks for the precise reports; the thread sample and the clean-env repro were what made this quick to pin down.
Correction to my note above: development builds are no longer published to PyPI (see #1353 — they were being picked up by --prerelease=allow installs). The fix for this issue is on main and ships in the next release; to try it before then, install from git: uv tool install "basic-memory @ git+https://github.com/basicmachines-co/basic-memory" --prerelease=allow.
Activity
phernandez commentedon Aug 28, 2026
Fixed by #1349 (on
mainnow, so it's in the next.devbuild on PyPI and will ship in the next patch release). Root cause wasnest_asyncio, applied for Alembic on Python < 3.14, swallowing the callback anyio uses to stop its worker thread after a sync FastAPI dependency ran — details in the PR. Thanks for the precise reports; the thread sample and the clean-env repro were what made this quick to pin down.fix(cli): stop stranding anyio worker threads on command exit
phernandez commentedon Aug 28, 2026
Correction to my note above: development builds are no longer published to PyPI (see #1353 — they were being picked up by
--prerelease=allowinstalls). The fix for this issue is onmainand ships in the next release; to try it before then, install from git:uv tool install "basic-memory @ git+https://github.com/basicmachines-co/basic-memory" --prerelease=allow.