Summary
GET /api/gpu/detailed returns 503 "No GPU data available" on Apple Silicon installs, while GET /api/features.gpu correctly reports the Apple M-Series GPU on the same service. The detection function exists and works — the router just doesn't wire it for GPU_BACKEND=apple.
Reproduction
On a healthy Apple Silicon install (GPU_BACKEND=apple in .env):
API_KEY=$(grep '^DASHBOARD_API_KEY=' ~/dream-server/.env | cut -d= -f2-)
# Fails:
curl -s -H "Authorization: Bearer $API_KEY" http://127.0.0.1:3002/api/gpu/detailed
# → {"detail":"No GPU data available"} (HTTP 503)
# But this succeeds on the same backend:
curl -s -H "Authorization: Bearer $API_KEY" http://127.0.0.1:3002/api/features | jq .gpu
# → {"name":"Apple M-Series (24 GB Unified)","vramGb":24.0,"tier":"Strix Halo Compact"}
Root cause
dream-server/extensions/services/dashboard-api/routers/gpu.py:42-49:
def _get_raw_gpus(gpu_backend: str) -> Optional[list[IndividualGPU]]:
"""Return per-GPU list from the appropriate backend, with fallback."""
if gpu_backend == "amd":
return get_gpu_info_amd_detailed()
result = get_gpu_info_nvidia_detailed()
if result:
return result
return get_gpu_info_amd_detailed()
No apple branch. When GPU_BACKEND=apple the code falls through to NVIDIA → AMD detection (both fail on Apple hardware) → empty list → HTTPException(503) at line 108.
Meanwhile gpu.py::get_gpu_info_apple() exists and works (proven by /api/features.gpu).
Suggested fix
Add an Apple branch in _get_raw_gpus(). Since Apple Silicon is a single integrated GPU with unified memory, wrap get_gpu_info_apple() into a single-element list[IndividualGPU]:
def _get_raw_gpus(gpu_backend: str) -> Optional[list[IndividualGPU]]:
if gpu_backend == "apple":
info = get_gpu_info_apple()
return [_to_individual(info)] if info else None
if gpu_backend == "amd":
return get_gpu_info_amd_detailed()
result = get_gpu_info_nvidia_detailed()
if result:
return result
return get_gpu_info_amd_detailed()
_to_individual() would convert the existing GPUInfo into an IndividualGPU (set gpu_id=0, copy memory/name fields). Alternatively, add get_gpu_info_apple_detailed() in gpu.py that returns list[IndividualGPU] directly.
Not a regression
git blame shows _get_raw_gpus() was introduced by commit c3e54d23 which is already on upstream/main. This bug pre-dates the current batch of open PRs; it's a feature gap from when multi-GPU monitoring was added (NVIDIA+AMD only).
Workaround
Dashboard Monitor / per-GPU cards will simply not populate on Apple. Use /api/features (already works) or the CLI (dream-cli gpu status — Apple-aware since PR Light-Heart-Labs#999/Light-Heart-Labs#1016).
Summary
GET /api/gpu/detailedreturns503 "No GPU data available"on Apple Silicon installs, whileGET /api/features.gpucorrectly reports the Apple M-Series GPU on the same service. The detection function exists and works — the router just doesn't wire it forGPU_BACKEND=apple.Reproduction
On a healthy Apple Silicon install (
GPU_BACKEND=applein.env):Root cause
dream-server/extensions/services/dashboard-api/routers/gpu.py:42-49:No
applebranch. WhenGPU_BACKEND=applethe code falls through to NVIDIA → AMD detection (both fail on Apple hardware) → empty list →HTTPException(503)at line 108.Meanwhile
gpu.py::get_gpu_info_apple()exists and works (proven by/api/features.gpu).Suggested fix
Add an Apple branch in
_get_raw_gpus(). Since Apple Silicon is a single integrated GPU with unified memory, wrapget_gpu_info_apple()into a single-elementlist[IndividualGPU]:_to_individual()would convert the existingGPUInfointo anIndividualGPU(setgpu_id=0, copy memory/name fields). Alternatively, addget_gpu_info_apple_detailed()ingpu.pythat returnslist[IndividualGPU]directly.Not a regression
git blameshows_get_raw_gpus()was introduced by commitc3e54d23which is already onupstream/main. This bug pre-dates the current batch of open PRs; it's a feature gap from when multi-GPU monitoring was added (NVIDIA+AMD only).Workaround
Dashboard Monitor / per-GPU cards will simply not populate on Apple. Use
/api/features(already works) or the CLI (dream-cli gpu status— Apple-aware since PR Light-Heart-Labs#999/Light-Heart-Labs#1016).