Skip to content

fix: declare numpy and httpx as runtime dependencies - #327

Merged
smaramwbc merged 1 commit into
mainfrom
fix/declare-runtime-deps
Aug 5, 2026
Merged

fix: declare numpy and httpx as runtime dependencies#327
smaramwbc merged 1 commit into
mainfrom
fix/declare-runtime-deps

Conversation

@smaramwbc

Copy link
Copy Markdown
Owner

numpy and httpx are imported directly by server/, but neither is declared. They arrived transitively — and one of those paths has already disappeared, so this is a live bug in the published image.

numpy — currently broken in production

server/api/admin.py imports numpy in two endpoints, unguarded:

admin.py:1491 detect_memory_conflicts()np.array, np.linalg.norm, np.dot
admin.py:1830 memory_clusters()np.array, np.linalg.svd, np.zeros

numpy only ever reached us through pgvector, and pgvector 0.5.0 dropped it (requires_dist is ['numpy'] on 0.4.2, None on 0.5.0). pyproject.toml already requires pgvector>=0.5.0, so numpy is now guaranteed absent:

$ uv pip compile --extra llm pyproject.toml     # current main
64 packages, numpy: 0 occurrences, pgvector==0.5.0

$ docker build -t main . && docker run --rm main python -c "import numpy"
ModuleNotFoundError: No module named 'numpy'

Both call sites early-return when there are no rows, which is why the test suite never reaches them — the endpoints raise as soon as they have data.

httpx — breaks core-only installs

server/services/webhooks.py:197 imports httpx in _attempt_delivery(). It is present only via the llm extra's dependency graph (litellm → httpx), so pip install statewave without extras resolves 34 packages with no httpx and webhook delivery raises the same way. The shipped image happens to be fine because the Dockerfile installs .[llm].

Why nothing caught it

Both imports sit inside function bodies, so they never execute at import time. Startup succeeds, pytest passes, and the container smoke test passes — the failure only surfaces on a request that reaches the code.

tests/test_runtime_imports.py closes that gap: it walks the AST of server/, collects every third-party module imported inside a function, and asserts each is importable. Modules that legitimately ship in an extra and are guarded at the call site are allowlisted (litellm; opentelemetry, which is gated behind _HAS_OTEL in server/core/tracing.py).

Verified

Check Result
New test against an image built from main ❌ 2 failed (correctly catches the bug)
New test against this branch ✅ 2 passed
import numpy / import httpx in the built image ✅ numpy 2.4.6, httpx 0.28.1
Container boot + /healthz ✅ healthy in ~2s
Image size 132MB → 152MB (numpy)

numpy>=1.26,<3 covers the project's requires-python = ">=3.11"; the APIs in use are stable across 1.26 and 2.x.

Both are imported directly by server/ but neither was declared; they arrived
transitively, and one of those paths has already disappeared.

numpy is used by the conflict-detection and clustering admin endpoints
(server/api/admin.py). It reached us only through pgvector, and pgvector 0.5.0
dropped the dependency. Since pyproject already requires pgvector>=0.5.0, a
fresh install has no numpy: resolving the current manifest yields 64 packages
with numpy absent, and `python -c "import numpy"` in an image built from main
fails with ModuleNotFoundError. Both call sites are unguarded, so those two
endpoints raise as soon as they have rows to process.

httpx is used by webhook delivery (server/services/webhooks.py) and is present
only via the `llm` extra's graph, so a core-only install resolves 34 packages
without it and webhook delivery fails the same way.

Nothing caught this: the imports are inside function bodies, so startup, the
test suite and the container smoke test all pass — the failure only appears on
a request that reaches the code. Add tests/test_runtime_imports.py, which walks
the AST of server/ and asserts every third-party module imported inside a
function is importable, allowing modules that ship in an extra and are guarded
at the call site (litellm, opentelemetry). It fails against an image built from
main and passes with this change.
@smaramwbc
smaramwbc merged commit 3e4a15e into main Aug 5, 2026
6 checks passed
@smaramwbc
smaramwbc deleted the fix/declare-runtime-deps branch August 5, 2026 21:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant