Skip to content

fix(lane host): a halt during the lone driver's prompt pass fails the request with its reason - #1133

Closed
chaog992 wants to merge 1 commit into
ashhart:mainfrom
chaog992:lane-host-lone-halt-reason
Closed

chaog992 wants to merge 1 commit into
ashhart:mainfrom
chaog992:lane-host-lone-halt-reason

Conversation

@chaog992

Copy link
Copy Markdown
Contributor

What this changes

A halt sets closing, so a prompt pass still running stops with error.Cancelled. The lane core's prompt passes end through LaneHost.cancel (zig/src/core/lane_host.zig:473), which fails the request with halt_reason, as its doc says ("what is left finishes failed with it", lane_host.zig:46). A lone driver's prompt pass instead ended as .cancelled with no message (zig/src/core/lane_host_lone.zig:66). It now ends through LaneHost.cancel too: without a halt, a cancel or a stop still ends cancelled; during a halt, the request fails with the reason; other errors are unchanged.

Where it shows: at the drain deadline (TF_DRAIN_S, 20 s by default) or on a second stop signal, the server halts the engine with "server restarting: retry shortly" (zig/src/server/serve.zig:253). Nemotron with its MTP head runs a lone driver and wires that halt, on Metal (zig/src/native/metal.zig:267) and on CUDA (zig/src/native/cuda.zig:128, not with --record); the other hosts with a lone driver wire no halt and are unchanged. A request whose prompt pass was in that driver got HTTP 200 with finish_reason: "cancelled" and empty content (streamed: a last "cancelled" chunk), and /v1/messages and /v1/responses read it as a finished turn (end_turn, completed). It now gets what drain_test pins for the requests a halt ends (zig/src/server/drain_test.zig:288): a 500 with "server restarting: retry shortly", or, streamed, a server_error event. A request still queued at the halt can reach the lone driver too, once the round in flight frees its lane; it now fails with the reason as well.

Receipt

  • Environment: base d1018b3 (main, 1.1.1 merged), fix d119bdb. Zig 0.17.0, Linux x86_64 under WSL2, no GPU used, no model.
  • Exactness: n/a: no token changes; only how a halted lone prompt pass ends.
  • Decode speed: n/a: an error path.
  • Prompt speed: n/a: the change runs only after a lone driver's prompt pass has failed.
  • Tests run (each exits 0 unless noted):
    • New test in zig/src/core/lane_host_lone_test.zig, on the fake target: the lone driver holds its prompt pass on an event until the halt is requested, so the pass then finds the host closing; the request must end failed with the halt's reason, with no tokens, no lane left and its lane released once. It waits on events, not on time: 20 of 20 runs pass in Debug and in ReleaseSafe.
    • The lane-host tests, zig test -lc -O <mode> --dep lanes --dep sys -Mroot=zig/src/core/engine_api.zig --dep sys -Mlanes=zig/src/core/lanes/lanes.zig -Msys=zig/src/platform/sys.zig: 218/218 in Debug, ReleaseSafe and ReleaseFast (217/217 on the base). zig build test-lane-api-host: 218/218 (217/217); zig build test-lane-halt-host: 14/14 (13/13).
    • zig build test test-kernel-contract test-golden fuzz-cortheon: 226/230 steps, 3035/3051 tests, 14 skipped, 2 failed, exit 1 (3033/3049 on the base, with the same two failures; the suite runs the lane-host tests in Debug and in ReleaseFast, so the new test counts twice). The two are digest_cache_test's and cuda_cost_identity's same-size rewrite tests, whose rewrite usually lands inside one file-time tick on this WSL2 machine (glm/cuda: load and serve nvidia/GLM-5.3-Flash-FP4-Local as stored #1050's receipt reports the second on plain v1.1.1 too). Server goldens 306/319 and 26/26 equal, 0 unexpected, as on the base.
    • Plain zig build: 24/24 steps. tools/zig/lean_check.py: the same 444 problems as the base, exit 1 on both, none in the touched files; tools/zig/lean_new.py against the base: 0 new. zig fmt --check build.zig zig and git diff --check pass.
    • Outside this PR: a probe shows the queued case ending cancelled with no message on the base and failed with the reason with the fix, and a randomized lane-host harness that halts at random points finds requests ending cancelled that nothing cancelled on the base, and none with the fix.
  • Failing receipt: the new test on the base's lane_host_lone.zig fails in Debug, ReleaseSafe and ReleaseFast: expected .failed, found .cancelled (zig/src/core/lane_host_lone_test.zig:171).
  • Not run, and why: no Mac and no GPU or model, so no Nemotron server drained on Metal or CUDA; the HTTP effect above comes from reading the server code and drain_test. The lane-host tests compile for aarch64-macos with -mcpu apple_m1 --test-no-exec, a compile check only.

Checklist

  • Every token still goes through the lane rounds. No serial path, and nothing that needs drafts off. (Unchanged: the change only decides how a failed lone prompt pass ends.)
  • Drafted output equals "draft": false, a resumed prompt equals a fresh one, and concurrent equals solo. (n/a: no tokens change.)
  • No precision traded for speed. If the bits change, the description says which sums change and why. (No arithmetic changes.)
  • A new or changed GPU kernel is registered with the kernel contract (docs/kernel-contract.md); each backend's SUMMARY line is in the receipt. (n/a: no kernel changes.)
  • Prompt processing is no slower than the last release. (n/a: an error path after a failed prompt pass.)
  • The description says which platforms I ran, Metal M1 to M5 and CUDA, and which I could not.
  • New tests fail before the change, pass after it, and skip cleanly without their dependency. (It needs no model or GPU and never skips.)
  • Comments and docstrings are one line. No measurements or history in the source.
  • No personal data, machine names, internal hosts or local paths. No AI attribution lines.

… request with its reason

The lone driver's error path ended a request whose prompt pass returned
error.Cancelled as cancelled with no message, without reading
halt_reason, so a halt during that pass ended the request "cancelled"
where the lane core's prompt passes fail it with the halt's reason. It
now ends through LaneHost.cancel, as theirs do.
@ashhart

ashhart commented Oct 21, 2026

Copy link
Copy Markdown
Owner

Thank you. This is on main as 010850d, with your authorship: a halt during the lone driver's prompt pass now ends the request through LaneHost.cancel, so it fails with the halt's reason ("server restarting: retry shortly") instead of finishing cancelled with an empty reply, and your test pins the single lane release. It ships with the next release. Closing as landed.

- Synthema, Ash's AI Assistant.

@ashhart ashhart closed this Oct 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants