Skip to content

fix(run): cancel streamed models when input guardrails fail - #4004

Merged
seratch merged 2 commits into
openai:mainfrom
hsusul:fix/streamed-input-guardrail-error-cleanup
Jul 29, 2026
Merged

fix(run): cancel streamed models when input guardrails fail#4004
seratch merged 2 commits into
openai:mainfrom
hsusul:fix/streamed-input-guardrail-error-cleanup

Conversation

@hsusul

@hsusul hsusul commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Summary

This pull request fixes a streamed-run deadlock when a parallel input guardrail raises an ordinary exception before the model emits an event.

The streamed guardrail task now cancels the in-flight run loop and wakes the event consumer after draining sibling guardrails. This lets stream_events() propagate the original guardrail exception and await model cancellation instead of hanging on an empty queue and leaving an unretrieved task exception.

Test plan

  • Confirmed the new regression test fails three consecutive times on upstream/main with a one-second timeout in stream_events() and an unretrieved ValueError.
  • uv run pytest -q tests/test_guardrails.py::test_parallel_guardrail_error_cancels_streaming_model (5 consecutive passes)
  • uv run pytest -q tests/test_guardrails.py (44 passed)
  • uv run pytest -q tests/test_agent_runner_streamed.py (55 passed)
  • uv run pytest -q tests/test_cancel_streaming.py (11 passed)
  • bash .agents/skills/code-change-verification/scripts/run.sh
  • make format-check
  • make tests-asyncio-stability
  • make coverage (5,806 passed, 7 skipped; 90% coverage)
  • Focused regression test on Python 3.10.20 and Python 3.14.6

Issue number

N/A — no pre-filed issue is required for this focused bug fix.

Checks

  • I've added new tests, if relevant
  • I've run .agents/skills/code-change-verification/scripts/run.sh
  • I've confirmed all verification steps pass
  • If using Codex, I've run /review before submitting this PR

@seratch seratch left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks for the contribution. The underlying deadlock is valid, and the guardrail-first fix is directionally correct. One interleaving still needs to be addressed before merge.

If the model fails first, the run loop marks the result complete and enters its finally block, where it awaits the input-guardrail task. If that guardrail then raises, the new unconditional run_loop_task.cancel() cancels a run loop that is already finalizing, which can skip computer disposal and span/trace completion.

Please cancel the run loop only while streamed_result.is_complete is false, and add a controlled model-first/guardrail-second regression test that verifies finalization still completes and the run-loop task is not cancelled. Once that is covered, this should be ready for another review.

@seratch seratch added this to the 0.19.x milestone Jul 29, 2026
@seratch
seratch merged commit 3142f3a into openai:main Jul 29, 2026
9 checks passed
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.

2 participants