transport is poisoned: an Engram disk stall, not a RoCE fault (2026-11-03)The prod FLARE lane on dgx1–4 (dsv41-flash-1017-4x-flare-gb10-prod4) died
repeatedly with two messages that look like fabric failures:
tensor-parallel peer failed: RoCE collective on rank 2 timed out waiting for
rank 0, HCA 0, at sequence 7122648; the transport is poisoned
RDMA write to rank 3 failed: transport retry counter exceeded
(vendor_err 0x81, seq 250342)
They are not fabric faults on this stand. The first is the collective spin-wait expiring because a peer rank is starved on disk-backed Engram reads; the second belongs to a different, rarer class (real QP retry exhaustion) and did not reproduce in any 2026-11-03 run. Everything below is measured, on the production package and flags.
RoCE collective … timed out … transport is poisoned — the b12x/RoCEnante
GPU kernel polls a peer's stripe flag for DEFAULT_SPIN_LIMIT = 20_000_000
polls (≈20 s on GB10; compiled into the prepared package, not a
serve-time flag) and then poisons the transport. FLARE is fail-stop: no
retry, no reroute, restart every rank.flare_engram_disk_wait_nanoseconds_total on the starved rank:
prefill advances in bursts, GPU idle 10–20 s at a time, and the slowest
reader still gets its data — the peer's spin limit expires first.ESL01TBTLCZ-27J2-TYN 1 TB drive except dgx4, which carries a
KingSpec XG7000-2TB 2242 (fw GT0d9d63, vid 0x1e4b) — a budget
consumer drive, no first-party firmware tool, our firmware not even listed
in the public database (SN13683 is what smarthdd knows for this model).
Sustained random-read ceiling measured on the wedge node: ≈29 K IOPS
(4 threads, O_DIRECT 4 K, 10 s) vs ≈33 K on a healthy dgx5 — while a
first-touch prefill demanded ≈24 K reads/s, i.e. 80–90 % of the drive.main — partially. Same hardware, same
package, same prompt: 3/3 wedges before, clean run after on a warm stand
(numbers below). On a freshly rebooted node the cold-boot wedge persists:
2026-11-04, 07:12 UTC boot, first long request ~9 min later died at
sequence 93 with prefill frozen at token 1 — dgx4's drive could not
deliver the first chunk's ≈350 MB of rows within the ≈8 s spin window even
with the parallel reader (its reads ran hot at ≈87 K reads/s for ~4 s and
then stalled mid-burst). Removing dgx4 remains the only complete fix on
this hardware; the reader patch is strictly beneficial but not sufficient
on a cold stand.| # | arrangement | runtime | result |
|---|---|---|---|
| 1 | orbit prod4, rank 0 = dgx4 |
packaged flare |
poison @ seq 7122648 (93 K tokens prefilled) |
| 2 | orbit prod4, rank 0 = dgx4 |
packaged flare |
poison @ seq 2109 (frozen ~93 K) |
| 3 | orbit prod4, rank 0 = dgx4 |
packaged flare |
poison @ seq 1284 (frozen ~61 K) |
| 4 | orbit prod4b, rank 0 = dgx1, dgx4 = rank 3 |
packaged flare |
poison @ seq 1557 (rank 1 waiting for rank 3) |
| 5 | orbit prod5 = dgx1+dgx2+dgx3+dgx8, no dgx4 |
packaged flare |
clean, 0→157,086 in ~61 s (×2) |
| 6 | orbit prod4b, dgx4 = rank 3 |
main + PR #184 | clean, 0→157,086 in ~60 s (~2,600 t/s) — warm stand |
| 8 | orbit prod4b (2026-11-04, freshly rebooted node) |
main + PR #184 | poison @ seq 93, prefill frozen at token 1 — the cold-boot case survives the reader patch |
| 7 | orbit sparks = dgx5–8 (2 runs, incl. after 45 min idle) |
packaged flare |
clean |
Runs 4 and 6 matter most: with dgx4 demoted from rank 0 the failure followed the node, not the rank. Run 5 isolates it further: remove dgx4 entirely and the packaged binary is clean. The wedging pair is always a peer waiting on dgx4's data. Run 8 adds the cold-boot dimension: the reader patch rescues a warm stand but not the first long request after a reboot — the drive stalls mid-burst inside the spin window at chunk 1.
prod4, layout ESP)| t | prefill | engram disk reads | disk wait (cum) |
|---|---|---|---|
| 20:52:55 | 52,993 | 2.32 M | 17.01 s |
| 20:52:56–59 | frozen | +108 K reads | 17.01 s (frozen) |
| 20:53:00–01 | frozen | slow | 27.17 s (+10.2 s in 2 s) |
| 20:53:02 | burst → 61,185 | +2.6 K | 27.17 s |
| 20:53:03–08 | frozen | frozen | 27.17 s |
| 20:53:09 | server dead — poisoned, seq 1284 |
The disk queue backs up while the GPU starves; engram_row_cache_misses
keeps climbing (69 % miss with the 1 GiB row cache the package recommends for
unified-memory GB10).
local_ack_timeout_err, req_transport_retries_exceeded, req_cqe_error:
0 everywhere, all day. out_of_sequence / packet_seq_err /
roce_adp_retrans are non-zero but flat-rate and retried successfully
(98.7 M RDMA write requests on dgx4). rx_write_requests freezes on all four
ranks simultaneously at the wedge — writes stop because the producer stopped,
not because the fabric dropped them. No mlx5/Xid events in the journal.
--embedding-table-cache-size 4GiB (from 1 GiB): wedged faster
(froze ~35 K). More cached rows did not change the read burst pattern.--embedding-table-workers 4: rejected —
parallel embedding disk workers require Windows. The Linux multi-lane
reader exists only as unmerged PR #184.ping -M do -s 8972
clean, SMART clean (media_errors 0, num_err_log_entries 0, 42 °C).pr184-on-main = NVIDIA/spark-local-inference main (44ec239) +
cherry-pick of PR #184 4ed10e1b ("Run parallel Engram disk workers on Linux
with io_uring lanes"). Cherry-pick merges cleanly; 5 files, +508/−309, all in
the runtime (helios/src/engram/reader*, runtime_package/selection.rs,
docs/cli-design.md) — no package ABI change, the same prepared packages
serve unchanged. Release build aarch64 on a Spark: ~50 s.
Deployed with orbit run --executable /home/kilork/flare-patched/flare
(launcher: executable in [flare.clusters.<cluster>]), packaged agent
install untouched.
Result (run 6): prefill 0 → 157,086 tokens in ~60 s, no burst gaps, total
engram_disk_wait 48.7 s — statistically identical to the healthy dgx5
lane (48.4 s). dgx4's KingSpec drive is still the slowest disk in the fleet;
the pipelined reader simply keeps it under the collective's patience.
But not on a cold stand (run 8, 2026-11-04): after a node reboot the
first long request wedges at sequence 93, prefill frozen at token 1. Rank
0's 1 Hz capture shows the first chunk's reads running hot (≈87 K reads/s,
disk wait +2.7 s) and then the whole runtime dead within ~8 s — dgx4's drive
stalls mid-burst inside the spin window, which the parallel reader raises in
throughput but cannot bound in time. Operationally this means: after every
reboot, a cold stand can lose its first long prompt even with the patch.
The production lane therefore excludes dgx4 (prod-no4) until the drive is
replaced; the prod4b+patch configuration is reserved for after the swap.
prod-no4 = dgx1+dgx2+dgx3+dgx8 (orbit prod5, rank 0
= dgx1), recipe dsv41-flash-1017-4x-flare-gb10-nodgx4. Clean on the same
prompts that killed the dgx1–4 lane, with or without the reader patch.prod4b + executable stays configured for after the NVMe swap
(Samsung PM9A3/PM9E1 M.2 2242 or Corsair MP700 Micro class; back up
~/.config/flare/orbit/controller.key before the DGX OS reinstall to skip
re-pairing).prod4 orbit (rank 0 = dgx4) remains in orbit.toml for reference.NVIDIA/spark-local-inference (was flare-local-inference)docs/multi-host.md,
docs/roce-ring.md): "A collective failure invalidates the serving run …
stop and restart all ranks together".sequence 1 with two rails on the f1 functions; a commenter serves fine
on f0. Not this failure (ours is mid-run and needs no second rail).helios/native/roce_proxy.c) has not changed since
e350914a (2026-10-21) apart from chain support and licensing./metrics — the ranks that wait are
blind.Title: Disk-Engram read stall on one rank poisons the TP transport (
RoCE collective … timed out … transport is poisoned) — reproduced 3/3, fixed by PR #184's io_uring readerSummary. On a 4× DGX Spark (GB10) TP4 lane serving
local-inference-lab/DeepSeek-V4.1-Flash-1017-FLARE(gb10,--embedding-table-storage disk --embedding-table-cache-size 1GiB --embedding-table-resident-scales,--max-concurrency 32 --mtp-draft-tokens 5 --mtp-adaptive-verification), a 157 K-token first-touch prompt kills the run on the same hardware it serves well otherwise:RoCE collective on rank 2 timed out waiting for rank 0, HCA 0, at sequence 7122648; the transport is poisonedDiagnosis. Rank 0's
/metricsshows stop-and-go prefill:flare_prefill_tokens_totalfrozen for 3–6 s at a time whileflare_engram_disk_wait_nanoseconds_totaljumps (+10.2 s within one 2 s window) andflare_engram_row_cache_misses_totalclimbs at ≈24 K random-reads/s — 80–90 % of that node's measured 4 K O_DIRECT ceiling (≈29 K IOPS). The waiting rank hits the 20 M-poll kernel spin limit (DEFAULT_SPIN_LIMIT, compiled into the package) and poisons the transport. RDMA counters are clean throughout:local_ack_timeout_err,req_transport_retries_exceeded,req_cqe_errorall 0;rx_write_requestsfreezes on every rank because the producer stopped.Rank-0 role is not the trigger. Reordering the orbit so another node is rank 0 still fails — the same node's data is what the peer waits for. Removing that node from the cluster (dgx1+dgx2+dgx3+dgx8) serves the same prompt cleanly with the packaged binary.
Fix (partial). Current
main+ PR #184 cherry-picked (pr184-on-main) serves the identical package and prompt on a warm stand: prefill 0→157 K in ~60 s, total Engram disk wait 48.7 s (healthy-lane parity), no poison — 1/1 after 3/3 failures without it. On a freshly rebooted node the wedge persists (2026-11-04): the first long request dies atsequence 93with prefill frozen at token 1 — the first chunk's ≈350 MB of rows must arrive within the ≈8 s spin window and the slow drive stalls mid-burst (reads hot at ≈87 K/s, then the runtime is dead). Excluding that node from the cluster (dgx1+dgx2+dgx3+dgx8) is the only configuration that survived every case, with or without the patch.Requests.
- Reconsider #184: its close reasoning ("the filesystem was the bottleneck") holds for Btrfs, but on ext4/GB10 the single-lane reader is what makes a warm stand survive a disk that is merely slow.
- Make the collective spin limit configurable at serve time (or make it Engram-aware / auto-extend on the first chunks of a cold stand) — it is currently baked into the prepared package, so operators cannot trade latency for stability. The cold-boot case (run 8) dies at token 1: no reader improvement fixes a deadline that is shorter than the first chunk's cold read time.
- Expose
/metricson every rank (or at least the readiness/disk counters): the rank that waits is invisible today, which turns a disk stall into an unattributable fabric error.- Consider a preflight/warning when a host's Engram disk falls below the package's implied read rate; a 6 W consumer 2242 at 29 K IOPS is not the same class as the reference platforms. A serve-time flag to shrink the prefill chunk (package-baked at 4096 tokens here) would also bound the per-chunk read volume on slow disks.
prod4b (dgx1 → dgx2 → dgx3 → dgx4,
rank 0 = dgx1) + executable = /home/kilork/flare-patched/flare
(staged on all four prod nodes; only the controller's copy is uploaded).prod4 (rank 0 = dgx4) is kept in orbit.toml for rollback; prod5
(dgx1+dgx2+dgx3+dgx8) is the no-dgx4 control.XG7000-2TB 2242 with an enterprise-class 2242 (Samsung PM9A3/PM9E1 M.2
2242, or Corsair MP700 Micro) — the software patch buys stability, not a
fast disk. Back up ~/.config/flare/orbit/controller.key first: restoring
it after a DGX OS reinstall avoids re-pairing all eight agents.