4.1 KiB
name, description
| name | description |
|---|---|
| radiance-endpoint-silent-wedge-triage | Diagnose a radiance (frank-archon) endpoint that is wedged or crawling while systemd says active(running) and /health answers 200 — separate engine-state wedge from config, hardware, swap and clock causes, and prove the restart fixed it. |
Silent wedge: active (running) + /health 200, but no throughput
For radiance endpoints (frank-archon, root unit whose ExecStart is exec podman wait). The unit can only exit when the container dies, so a stalled engine loop never triggers Restart=always, up stays 1, and Alertmanager stays empty (every rule keys on up==0, num_requests_waiting>0, or TTFT p95). Verified 2026-10-30 21:00 on dankserver.
Triage ladder (in this order — each step kills a class)
- Front end vs engine split.
curl -w '%{time_total}' /healthvs/v1/models. A 0.4 ms/healthbeside a 20 s/v1/modelstimeout = front end alive, engine loop stalled. - Unit truth, not the port.
systemctl status frank-archon -n 0+systemctl show -p MainPID,DropInPaths,ExecMainStartTimestamp. A 4 h-old unit on a 2-week-old host means a restart happened today — cross-checkjournalctl -u <svc> --since <day>forStarting/Stopping/exitandgit log -- scripts/<svc>.*to see whether a deploy caused it. Non-emptyDropInPaths= leftover bench arm (separate trap). - Container storage namespace. The unit is
User=dank, so the container lives in rootless storage:sudo podman ps -alists nothing andpodman inspectsaysno such object— query as the user, without sudo. - Engine's own voice (the decisive artifact).
podman logs --timestamps frank-archon | grep "E device:".a synchronisation has seen no queue advance for 5 snamingbarrier-and dep[0]=1on both ranks = the TP all-reduce never completed. Timestamp the first occurrence; that is the incident start. - Rule out the engine's own suggested causes before believing anything else:
cat /sys/module/amdgpu/parameters/cwsr_enable(its message blamescwsr_enable=0;1falsifies it). Swap: read/proc/<engine-pid>/statusVmSwap — do NOT infer fromfree//proc/swapstotals (host-wide swap can be 32 GiB while the engine holds 378 MiB). Clocks during load: fire a request, thenrocm-smi --showclocks --showperflevel --showpower+/sys/class/drm/cardN/device/gpu_busy_percent— 100 % busy at full sclk means neither throttle nor starvation. - Quantify the collapse from counters, not vibes.
radiance:engine_step_seconds_decode_total÷radiance:engine_steps_decode_total= mean decode step time; diff two scrapes (Δseconds ÷ Δsteps) for the current rate. Compare to the shape's recorded baseline in the endpoint's vault page (15.5 ms at frank-archon's 4×200000 fp8 shape; 209 ms = 13× collapse).
Proof of fix (same-request A/B, not a health check)
Submit one fixed request before and after the restart and diff the engine's own timings object — an 8-token probe measures only first-token noise, use max_tokens>=128:
curl -sS -m 240 -o /tmp/q.json -X POST :7770/v1/chat/completions \
-H 'Content-Type: application/json' -d @/tmp/query.json # then read timings.predicted_per_token_ms / predicted_per_second / ttft_ms / draft_n / draft_n_accepted
Before/after on the identical request: 90.76 → 11.06 ms/token, 11.02 → 90.40 t/s, ttft 420 → 148 ms, acceptance unchanged (266/266). Then re-read the boot ledger (elastic / kv cache / vram_weights / unclaimed / sampler rows) and confirm it matches the page's recorded ledger — a successful restart proves nothing about the flags. Close with the restore oracle: is-active and is-enabled and no /run/systemd/system/<unit> mask symlink and container owned by the unit and DropInPaths empty.
Law
A wedged radiance engine has no in-place recovery (its own wording: "a queue the driver evicted and could not restore") — systemctl restart is the only cure, and the fix must be proven by a rate, never by /health. Durable gap: no alert fires on a live-but-stalled endpoint; the missing rule is a decode-step-time ratio gated on up==1 in shared/prometheus/rules/llm-fleet.yml.