fix: declare numpy and httpx as runtime dependencies - #327
Merged
Conversation
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
numpyandhttpxare imported directly byserver/, 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.pyimports numpy in two endpoints, unguarded:admin.py:1491detect_memory_conflicts()—np.array,np.linalg.norm,np.dotadmin.py:1830memory_clusters()—np.array,np.linalg.svd,np.zerosnumpy only ever reached us through pgvector, and pgvector 0.5.0 dropped it (
requires_distis['numpy']on 0.4.2,Noneon 0.5.0).pyproject.tomlalready requirespgvector>=0.5.0, so numpy is now guaranteed absent: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:197imports httpx in_attempt_delivery(). It is present only via thellmextra's dependency graph (litellm → httpx), sopip install statewavewithout 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,
pytestpasses, and the container smoke test passes — the failure only surfaces on a request that reaches the code.tests/test_runtime_imports.pycloses that gap: it walks the AST ofserver/, 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_OTELinserver/core/tracing.py).Verified
mainimport numpy/import httpxin the built image/healthznumpy>=1.26,<3covers the project'srequires-python = ">=3.11"; the APIs in use are stable across 1.26 and 2.x.