TL;DR: npm install -g does not guarantee execute bits. PermissionError ≠ CalledProcessError. Never hardcode model names — query the backend at runtime.
capture_output=Truehides all subprocess output — bootstrap appears frozennpm install -gmissing execute bit — binary found byshutil.which()butsubprocess.run()raisesPermissionError: [Errno 13]- Hardcoded model names — LM Studio
400, Ollama404when model not loaded
| File | Issue | Fix |
|---|---|---|
openclaw_bootstrap.py |
capture_output=True silenced install output |
Removed; output streams to terminal |
openclaw_bootstrap.py |
No execute-bit check after npm install -g openclaw |
Added chmod +x if S_IXUSR missing |
scripts/launch_researchers.py |
Hardcoded model names in researcher config | _resolve_ollama_model() + _resolve_lmstudio_model() with _pick_model_with_affinity() and _platform_for_role() — see 09-hardware-affinity |
orchestrator/agent_tracker.py |
AgentRecord(**v) crash on stale routing data |
_load() now isinstance(v, dict) guards every entry |
# execute bit check (openclaw_bootstrap.py)
import stat, shutil
from pathlib import Path
path = shutil.which("openclaw")
if path and not (Path(path).stat().st_mode & stat.S_IXUSR):
Path(path).chmod(Path(path).stat().st_mode | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH)
# exception handling
try:
subprocess.run(["openclaw", "--version"], check=True)
except subprocess.CalledProcessError as e:
print(f"openclaw exited with {e.returncode}")
except PermissionError:
print("Fix: chmod +x $(which openclaw)")
# runtime model discovery (scripts/launch_researchers.py)
def _resolve_ollama_model(host, port, preferred):
r = httpx.get(f"http://{host}:{port}/api/tags", timeout=5)
names = [m["name"] for m in r.json().get("models", [])]
return preferred if preferred in names else (names[0] if names else preferred)- Never use
capture_output=Truein bootstrap subprocess calls - After any
npm install -g, verify and fix execute bits - Catch
PermissionErrorseparately fromCalledProcessError - Never hardcode model names — query
/v1/modelsor/api/tagsat runtime AgentTracker._load()mustisinstance(v, dict)before**vunpacking
ffb1be0(PT) — fix(researchers): auto-discover loaded model via /v1/models + /api/tagsd9e4f50(PT) — fix(tracker): handle stale routing data in agents.json
- Session log 2026-04-07
- UTS/02 — same topic with UTS-specific files