mirror of
https://github.com/BigBodyCobain/Shadowbroker.git
synced 2026-05-28 10:01:31 +02:00
Fix #296: reject backend venvs missing uvicorn before launch
Reported by @f3n3k on Windows native install path. Symptom:
C:\001\backend\venv\Scripts\python.exe: No module named uvicorn
[backend] exited with 1
ShadowBroker has stopped. Exit code: 1
Root cause
----------
The Windows Start.bat flow chains:
Start.bat
└─ scripts\run-windows-runtime.ps1
└─ frontend\scripts\dev-all.cjs
└─ start-backend.js
└─ backend\venv\Scripts\python.exe -m uvicorn main:app
`start-backend.js` decided whether an existing `backend\venv` was usable
by calling `canRun(candidate, ["-V"])`. That only checks whether Python
itself can run — it does NOT check whether the backend's actual runtime
dependencies are installed.
When the venv exists but `pip install` never finished (partial install,
failed network, interrupted bootstrap, etc.), the launcher happily
accepted that broken venv, then died with the exact error f3n3k
reported.
Fix
---
New `canRunBackendPython()` helper that requires BOTH:
python -V # Python is runnable
python -c "import fastapi, uvicorn" # backend deps are installed
Used in two call sites:
* `ensureBackendVenv()` — when iterating candidate venvs on first
launch, reject any venv whose Python can't import the backend's
real entry-point deps. The launcher then falls through to its
existing rebuild path (`rebuildBackendVenv`) which reinstalls deps
before declaring the venv healthy.
* `rebuildBackendVenv()` — after a rebuild attempt, verify the deps
are present before returning the new interpreter path. Catches
silent partial rebuilds.
The check is the import that uvicorn itself would do at startup, so a
green return here genuinely means "uvicorn will start". Cost is one
extra `python -c` per venv candidate on launcher startup — milliseconds.
Verified locally with `node --check start-backend.js`.
Credit: @f3n3k for the original report.
This commit is contained in:
+9
-2
@@ -76,6 +76,13 @@ function canRun(command, args) {
|
||||
return !result.error && result.status === 0;
|
||||
}
|
||||
|
||||
function canRunBackendPython(pythonBin) {
|
||||
return (
|
||||
canRun(pythonBin, ["-V"]) &&
|
||||
canRun(pythonBin, ["-c", "import fastapi, uvicorn"])
|
||||
);
|
||||
}
|
||||
|
||||
function findBasePython() {
|
||||
const candidates = isWindows
|
||||
? [
|
||||
@@ -135,12 +142,12 @@ function rebuildBackendVenv(targetDir, basePython) {
|
||||
if (result.error || result.status !== 0) {
|
||||
return null;
|
||||
}
|
||||
return canRun(repairedBin, ["-V"]) ? repairedBin : null;
|
||||
return canRunBackendPython(repairedBin) ? repairedBin : null;
|
||||
}
|
||||
|
||||
function ensureBackendVenv() {
|
||||
for (const candidate of venvCandidates) {
|
||||
if (fs.existsSync(candidate) && canRun(candidate, ["-V"])) {
|
||||
if (fs.existsSync(candidate) && canRunBackendPython(candidate)) {
|
||||
persistSelectedVenv(candidate);
|
||||
return candidate;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user