You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
nemotron cuda: clear image spans after failed setup - #2985
Vision.begin now registers errdefer v.end() immediately after radio.plan
assigns the pass's spans. An ImageRows refusal or encoding error therefore
clears that metadata before returning; successful setup keeps the existing
caller-owned lifetime. The native offer test retains its successful planning
assertions and checks failed setup separately. Thanks, Ash, for tracing the failed setup into the next
text-only request and pointing to the focused host regression.
Why: each of the two forced setup failures retained 2 planned image regions
instead of leaving none (Receipt, focused comparison).
What was done: added failure cleanup and host checks for rejection, retry,
successful reuse and allocation failure.
Result: both forced failures now leave 0 planned regions; the unfiltered host
checks add 4 passing tests with no new skips or failures (Receipt, host comparison).
Receipt
Environment: baseline eab305db0091a23b28122caadc8bf069f53d211e, candidate 9d9112e914e1617ee773e92c6e933c117597f8ab, source version 1.2.7, Zig 0.17.0,
Apple M1 Pro with 16 GiB, macOS 26.6 (25G72), Xcode 27.2 (27B52).
No CUDA device, CUDA toolchain, checkpoint or drafter was used.
Boxes it reaches: Nemotron CUDA image setup, including video inputs already
represented as image spans. No kernel, precision, scheduler or budget changes.
Paths and platforms: the actual Vision.begin/end/empty-span splice path
ran on the Mac host; the real tower's shape refusal ran without a device.
The native lane caller was traced in source. Linux/Windows serving and CUDA
image execution were not run.
New switch: n/a, no setting added or changed.
Exactness: not run. No claim of drafted/plain, resumed/fresh or concurrent/solo
token equivalence follows from these host fixtures.
Main against this branch: host comparisons below; model comparisons cannot
run on the available hardware. No run on another machine is requested here.
Decode speed before/after: not measured; no CUDA hardware or checkpoint.
Prompt speed before/after: not measured, including cold 2k/8k/32k/64k prefill.
This change reaches prompt setup, so a host pass is not a performance receipt.
Memory: allocator-checked host lifetime tests only, not a peak physical
serving footprint or device/pinned allocation measurement.
Licence of new weights/drafter: n/a, none added.
Focused comparison
Each build uses a new local cache. Commands use the pinned Zig on PATH and
Xcode through DEVELOPER_DIR; FRESH_CACHE is a different empty directory per run.
Before the fix, the row-budget and injected encoder-error tests each fail expected 0, found 2. Removing only the cleanup line from the final candidate
also fails the adjusted real-tower-error assertion, expected 0, found 1.
The success/reuse and allocation-failure tests are controls and pass on main
as well as the fixed head. No tests were removed.
Named binary output confirms the original three image tests and the four new
ones execute. The existing cuda.zig test root imports this file, and that
root is included in test-cuda-host and the aggregate test step.
The first unfiltered host run also exposed an existing native offer test that
inspected spans after a deliberate tower error. The updated test retains its
successful planning checks at both prompt offsets using the existing host
encoder, then checks real tower errors leave empty spans. The selected offer
step passes 15/15; removing the cleanup line gives 14/15 at the intended expected 0, found 2 assertion. With cleanup restored, both selected steps
pass 35/35. This adds assertions to the existing test, not another test case.
Not run: full macOS test (includes Metal device checks), CUDA kernel/device
and model gates, Linux/Windows CI, token equality, served timing and memory. test-cuda-host is a subset, not a substitute for the complete suite.
The four new tests account for the entire count increase: the family runner
goes from 90 passed / 3 skipped / 93 total to 94 / 3 / 97. Every other runner's
counts are unchanged, including the native runner's 196 / 2 / 198. No tests
were removed. The focused success and allocation-failure controls pass on
main too; the cleanup regressions demonstrate the failure and correction.
Both revisions match 322/335 fake-server goldens, with the same 13 known
differences and 0 unexpected differences, and all 55 security goldens.
Host kernel-contract checks pass; fuzz is 22/22. These results are host checks,
not a CUDA device or checkpoint qualification.
Checklist
The title and description match the head commit, including the receipt and stack.
Cleanup regressions fail before and pass after; host tests need no GPU or decoder dependency.
Comments and docstrings are one line. No measurements or history in source.
No private data, machine names, internal hosts or local paths in the diff or commits. No AI attribution.
Lane-round selection is unchanged; no serial path or drafts-off requirement added.
Drafted/plain, resumed/fresh and concurrent/solo token equality measured.
No precision or arithmetic changes.
Decode and cold prompt performance measured against main at the required stream counts.
Thanks @jishnuvenugopal, this is the fix #2943 asked for. errdefer v.end() now sits right after radio.plan at zig/src/families/nemotron/cuda_vision.zig:73. A refused or failed begin leaves no spans behind, so the next text-only pass can't splice them in, and a successful begin keeps its spans as before.
We checked it on the head, 9d9112e91. The focused host steps pass, 35 of 35. With only the errdefer line removed, four tests fail with "expected 0, found 2" (or "found 1"): the two new failure tests, the tower-boundary test and the offer test. That matches your table. The offer test still checks its planning through the host encoder, CI is green, and the PR merges cleanly with today's main.
Thank you, @ashhart, for independently rerunning the focused checks and cleanup-removal control, and for handling the landing and CHANGELOG. I'll leave the tested head unchanged.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this changes
Vision.beginnow registerserrdefer v.end()immediately afterradio.planassigns the pass's spans. An
ImageRowsrefusal or encoding error thereforeclears that metadata before returning; successful setup keeps the existing
caller-owned lifetime. The native offer test retains its successful planning
assertions and checks failed setup separately. Thanks, Ash, for tracing the failed setup into the next
text-only request and pointing to the focused host regression.
eab305db0091a23b28122caadc8bf069f53d211e; this branch adds0de53388c,6784877afand9d9112e91.atc overlap --json: November 12, 2026, 01:33 UTC, against that baseline:Nemotron 3.5 Transcribe: audio input, the 65,536-token window, an hour of audio, MTP drafts #1632 clean, but incomplete because of PR-count, file-read and time limits.
A separate complete snapshot at 01:22 UTC covers 273 open PRs / 11,893
changed-file entries, including all 26 capped lists and eight refreshed heads.
cuda: GLM, MiniMax and Nemotron placed from one launch, by flags or aliases (T1b of #2560) #2919 and Nemotron 3.5 Transcribe: audio input, the 65,536-token window, an hour of audio, MTP drafts #1632 share the native offer file, in separate functions; neither
changes the other two files. Pinned textual merges at 01:26 UTC: Nemotron 3.5 Transcribe: audio input, the 65,536-token window, an hour of audio, MTP drafts #1632
(
d617fa794) is clean; cuda: GLM, MiniMax and Nemotron placed from one launch, by flags or aliases (T1b of #2560) #2919 (68c6d2dee) has six unrelated conflicts alsopresent against unchanged main, with identical conflict-stage blobs. No
conflict in this branch's files.
Verified outcome
instead of leaving none (Receipt, focused comparison).
successful reuse and allocation failure.
checks add 4 passing tests with no new skips or failures (Receipt, host comparison).
Receipt
eab305db0091a23b28122caadc8bf069f53d211e, candidate9d9112e914e1617ee773e92c6e933c117597f8ab, source version 1.2.7, Zig 0.17.0,Apple M1 Pro with 16 GiB, macOS 26.6 (25G72), Xcode 27.2 (27B52).
No CUDA device, CUDA toolchain, checkpoint or drafter was used.
represented as image spans. No kernel, precision, scheduler or budget changes.
Vision.begin/end/empty-spansplicepathran on the Mac host; the real tower's shape refusal ran without a device.
The native lane caller was traced in source. Linux/Windows serving and CUDA
image execution were not run.
token equivalence follows from these host fixtures.
run on the available hardware. No run on another machine is requested here.
This change reaches prompt setup, so a host pass is not a performance receipt.
serving footprint or device/pinned allocation measurement.
Focused comparison
Each build uses a new local cache. Commands use the pinned Zig on PATH and
Xcode through
DEVELOPER_DIR;FRESH_CACHEis a different empty directory per run.zig build test-modelopt-host -Dmodelopt-host-filter=cuda_vision \ -Dcpu=apple_m1 -j2 --cache-dir "$FRESH_CACHE" --summary all --verboseBefore the fix, the row-budget and injected encoder-error tests each fail
expected 0, found 2. Removing only the cleanup line from the final candidatealso fails the adjusted real-tower-error assertion,
expected 0, found 1.The success/reuse and allocation-failure tests are controls and pass on main
as well as the fixed head. No tests were removed.
Named binary output confirms the original three image tests and the four new
ones execute. The existing
cuda.zigtest root imports this file, and thatroot is included in
test-cuda-hostand the aggregateteststep.The first unfiltered host run also exposed an existing native offer test that
inspected spans after a deliberate tower error. The updated test retains its
successful planning checks at both prompt offsets using the existing host
encoder, then checks real tower errors leave empty spans. The selected offer
step passes 15/15; removing the cleanup line gives 14/15 at the intended
expected 0, found 2assertion. With cleanup restored, both selected stepspass 35/35. This adds assertions to the existing test, not another test case.
Checks on this head
9d9112e914e1617ee773e92c6e933c117597f8ab.checker on both.
lean_new.pyexits 0; the raw checker count is not zero.zig fmt --check build.zig zigandgit diff --check origin/main: pass.python3 tools/pr_check.py --base eab305db0: exit 0, no errors; one advisorybecause no PR number exists yet. No CHANGELOG or credits edit is included.
zig build -Dcpu=apple_m1 -j1 --cache-dir "$FRESH_CACHE" --prefix "$LOCAL_PREFIX" --summary all: all 285 steps succeed.test(includes Metal device checks), CUDA kernel/deviceand model gates, Linux/Windows CI, token equality, served timing and memory.
test-cuda-hostis a subset, not a substitute for the complete suite.Host comparison
Both revisions use fresh local caches:
zig build test-cuda-host test-golden test-kernel-contract fuzz-cortheon \ -Dcpu=apple_m1 -j1 --cache-dir "$FRESH_CACHE" --summary alleab305db09d9112e91The four new tests account for the entire count increase: the family runner
goes from 90 passed / 3 skipped / 93 total to 94 / 3 / 97. Every other runner's
counts are unchanged, including the native runner's 196 / 2 / 198. No tests
were removed. The focused success and allocation-failure controls pass on
main too; the cleanup regressions demonstrate the failure and correction.
Both revisions match 322/335 fake-server goldens, with the same 13 known
differences and 0 unexpected differences, and all 55 security goldens.
Host kernel-contract checks pass; fuzz is 22/22. These results are host checks,
not a CUDA device or checkpoint qualification.
Checklist