Skip to content

[None][fix] Fix Cosmos3 CUDA event crash when text guardrail blocks prompt - #17510

Open
ishovkun wants to merge 3 commits into
NVIDIA:mainfrom
ishovkun:cosmos3-fix-guardrail-event-crash
Open

[None][fix] Fix Cosmos3 CUDA event crash when text guardrail blocks prompt#17510
ishovkun wants to merge 3 commits into
NVIDIA:mainfrom
ishovkun:cosmos3-fix-guardrail-event-crash

Conversation

@ishovkun

@ishovkun ishovkun commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Dev Engineer Review

  • The guardrail early-exit path now returns PipelineOutput() directly.
  • This avoids elapsed-time calculation for unrecorded CUDA events.
  • Default timing fields remain 0.0.
  • The change introduces no API, dependency, configuration, or test-list changes.
  • The implementation is minimal and has low regression risk.

QA Engineer Review

  • Added test_blocked_prompt_returns_empty_output.
  • The test verifies that a blocked prompt returns empty video and image outputs with zero timing values.
  • The test is CUDA-gated.
  • No integration test-list coverage was identified for this test.
  • Verdict: needs follow-up.

Description

When the Cosmos3 text guardrail blocks a request, the early-exit path called
timer.mark_end() followed by timer.fill(PipelineOutput()). However,
mark_denoise_start() and mark_post_start() are never reached because the
guardrail check fires before any GPU generation work begins. CudaPhaseTimer.fill()
calls elapsed_time() on all four event pairs, so any unrecorded event raised:

ValueError: Both events must be recorded before calculating elapsed time.

This surfaced as a worker crash and a generation error visible to the client:

[TRT-LLM] [W] [_torch] Text guardrail blocked prompt
[TRT-LLM] [E] [_torch] Worker 0: Error: Both events must be recorded before calculating elapsed time.
[TRT-LLM] [E] [serve] Video request error: Generation failed: Both events must be recorded before calculating elapsed time.

Fix: return PipelineOutput() directly — there is nothing to time when
the request is blocked before generation begins. The timing fields on
PipelineOutput default to 0.0, which is the correct value for a blocked
(zero-generation-work) request.

Test Coverage

No existing test covers the guardrail-blocked early-exit path (the pipeline's
multi-process worker architecture makes it awkward to unit-test directly).
The fix is a two-line deletion with no new branching logic, so the risk is low.

PR Checklist

  • PR description clearly explains what and why. If using CodeRabbit's summary, please make sure it makes sense.
  • PR Follows TRT-LLM CODING GUIDELINES to the best of your knowledge.
  • Test cases are provided for new code paths (see test instructions)
  • No API changes introduced.
  • No new dependencies.
  • Please check this after reviewing the above items as appropriate for this PR.

…rompt

When the text guardrail blocks a request, the early-exit path called
timer.mark_end() and timer.fill(), but mark_denoise_start() and
mark_post_start() were never reached (generation had not started).
CudaPhaseTimer.fill() calls elapsed_time() on all four event pairs, so
any unrecorded event raised:

  ValueError: Both events must be recorded before calculating elapsed time.

The fix is to return PipelineOutput() directly — there is nothing to time
when the request is blocked before generation begins.

Signed-off-by: Igor Shovkun <ishovkun@nvidia.com>
@ishovkun
ishovkun force-pushed the cosmos3-fix-guardrail-event-crash branch from 30ff54f to 9fb3561 Compare August 11, 2026 18:18
@coderabbitai

coderabbitai Bot commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 4313684e-6916-4622-9085-284035af62e0

📥 Commits

Reviewing files that changed from the base of the PR and between 83570b1 and 0ede69f.

📒 Files selected for processing (1)
  • tests/unittest/_torch/visual_gen/test_cosmos3_pipeline.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/unittest/_torch/visual_gen/test_cosmos3_pipeline.py

Walkthrough

The Cosmos3 pipeline now returns an empty PipelineOutput directly when text guardrails block a request. The blocked path no longer updates phase timing data. A CUDA-gated test verifies the empty outputs and zero timing values.

Changes

Cosmos3 guardrail handling

Layer / File(s) Summary
Blocked-request output handling
tensorrt_llm/_torch/visual_gen/models/cosmos3/pipeline_cosmos3.py, tests/unittest/_torch/visual_gen/test_cosmos3_pipeline.py
The blocked-request branch returns an empty PipelineOutput without updating phase timing data. A CUDA-gated test verifies empty video and image outputs and zero timing values.

Estimated code review effort: 2 (Simple) | ~10 minutes

Suggested reviewers: qijune, schetlur-nv

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the Cosmos3 CUDA event crash and the guardrail-blocked prompt condition.
Description check ✅ Passed The description includes the required sections and clearly explains the issue, fix, test context, and checklist status.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

Exercises the early return on a bare pipeline instance: the guardrail
blocks before the text encoder, transformer and VAE run, so only the
config-derived attributes forward() reads on the way there are needed —
no weights, no GPU memory, and no unsafe prompt (the safety checker is
stubbed to report "unsafe" for any input).

Guards the regression directly: against the previous code the call
raised "Both events must be recorded before calculating elapsed time"
instead of returning an empty PipelineOutput.

Signed-off-by: Igor Shovkun <ishovkun@nvidia.com>

@brnguyen2 brnguyen2 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fix is right: fill() calls elapsed_time() on all four events, and only mark_pre_start() runs before the guardrail check, so the early exit was guaranteed to raise. Returning a default PipelineOutput() gives the correct 0.0 timings. This is the only early return in forward() ahead of the later marks, so no other path has the same problem.

One process note: bug fixes normally carry an NVBug in the title tag rather than [None] — worth filing/linking one if this was reported from a real run.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
tests/unittest/_torch/visual_gen/test_cosmos3_pipeline.py (1)

1135-1137: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Assert the complete empty PipelineOutput contract.

The PipelineOutput contract in tensorrt_llm/visual_gen/output.py at Lines 36-100 also defines audio, frame_rate, and audio_sample_rate. Add assertions for these fields so the test detects non-empty audio or metadata on a blocked request.

Proposed assertions
         assert result.video is None
         assert result.image is None
+        assert result.audio is None
+        assert result.frame_rate is None
+        assert result.audio_sample_rate is None
         assert (result.pre_denoise, result.denoise, result.post_denoise) == (0.0, 0.0, 0.0)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/unittest/_torch/visual_gen/test_cosmos3_pipeline.py` around lines 1135
- 1137, Extend the blocked-request assertions in the relevant test to cover the
complete empty PipelineOutput contract: assert result.audio is None,
result.frame_rate is None, and result.audio_sample_rate is None alongside the
existing video, image, and denoising checks.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tests/unittest/_torch/visual_gen/test_cosmos3_pipeline.py`:
- Line 1117: Remove the pipeline.rank = 0 assignment from the
Cosmos3OmniMoTPipeline test setup so it does not attempt to write the
getter-only BasePipeline.rank property; rely on the existing default rank value
of 0 when distributed state is uninitialized, allowing forward() to execute.

---

Nitpick comments:
In `@tests/unittest/_torch/visual_gen/test_cosmos3_pipeline.py`:
- Around line 1135-1137: Extend the blocked-request assertions in the relevant
test to cover the complete empty PipelineOutput contract: assert result.audio is
None, result.frame_rate is None, and result.audio_sample_rate is None alongside
the existing video, image, and denoising checks.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: cbb29cc9-b42a-4bff-b7f9-53f541623ca3

📥 Commits

Reviewing files that changed from the base of the PR and between 9fb3561 and 83570b1.

📒 Files selected for processing (1)
  • tests/unittest/_torch/visual_gen/test_cosmos3_pipeline.py

Comment thread tests/unittest/_torch/visual_gen/test_cosmos3_pipeline.py Outdated
…il test

``rank`` is a BasePipeline property that already resolves to 0 without a
distributed init, so assigning it raised AttributeError on the bare
instance. ``device`` is likewise a property, served by the transformer stub.

Signed-off-by: Igor Shovkun <ishovkun@nvidia.com>
@ishovkun

Copy link
Copy Markdown
Contributor Author

/bot run

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #65399 [ run ] triggered by Bot. Commit: 0ede69f Link to invocation

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #65399 [ run ] completed with state SUCCESS. Commit: 0ede69f
/LLM/main/L0_MergeRequest_PR pipeline #53157 completed with status: 'UNSTABLE'

CI Report

⚠️ Multi-GPU Label Required:
Multi-GPU tests require the ci: full pre-merge approved label on this PR. Ask a member of NVIDIA/trt-llm-ci-approvers to add the label, then re-trigger CI with the same bot command (no rebase needed).

⚠️ Action Required:

  • Please check the failed tests and fix your PR
  • If you cannot view the failures, ask the CI triggerer to share details
  • Once fixed, request an NVIDIA team member to trigger CI again

Link to invocation

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants