Skip to content

basic-memory schema validate prints its result then hangs instead of exiting (Python 3.13) #1345

Closed

Description

@WebKingdom

What happened

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.

Environment

  • Basic Memory v0.23.2 (c0bd87c6d5a4a58034b1d6c8c5018e443b0bd048)
  • CPython 3.13.15, macOS (Apple Silicon)

Happy to send a PR

I have a one-line fix and a regression test ready.

Activity

  1. phernandez commented on Aug 28, 2026

    @phernandez
    Member

    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.

  2. added a commit that references this issue on Aug 28, 2026
    b29b584
  3. phernandez commented on Aug 28, 2026

    @phernandez
    Member

    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.

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

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions