Skip to content

.NET: [Flaky test] InputWaiterTests.InputWaiter_WaitForInputAsync_CompletesWhenTimeoutExpiresAsync #7360

Description

@rogerbarreto

Summary

Microsoft.Agents.AI.Workflows.UnitTests.InputWaiterTests.InputWaiter_WaitForInputAsync_CompletesWhenTimeoutExpiresAsync fails intermittently in the merge_group, blocking the queue for PRs that do not touch the workflows code at all. The most recent occurrence blocked PR #7337, which only adds a sample.

Failure signature

failed Microsoft.Agents.AI.Workflows.UnitTests.InputWaiterTests.InputWaiter_WaitForInputAsync_CompletesWhenTimeoutExpiresAsync (5s 103ms)
  Expected object to refer to System.Threading.Tasks.Task`1[System.Threading.Tasks.VoidTaskResult] {Status=WaitingForActivation}
  because the wait task should complete once the timeout expires,
  but found System.Threading.Tasks.Task+DelayPromise {Status=RanToCompletion}.
   at FluentAssertions.Primitives.ReferenceTypeAssertions`2.BeSameAs(TSubject expected, String because, Object[] becauseArgs)

Affected runs

A scan of the last 18 failed dotnet-build-and-test runs found 7 occurrences of this exact failure, roughly 39% of the failed runs in that sample.

Run Date Event Job
https://github.com/microsoft/agent-framework/actions/runs/30299144911 2026-07-27 merge_group net472, windows-latest
https://github.com/microsoft/agent-framework/actions/runs/30293327057 2026-07-27 merge_group net472, windows-latest
https://github.com/microsoft/agent-framework/actions/runs/29760053213 2026-07-20 merge_group net472, windows-latest
https://github.com/microsoft/agent-framework/actions/runs/29312897500 2026-07-14 merge_group net472, windows-latest
https://github.com/microsoft/agent-framework/actions/runs/29284546765 2026-07-13 merge_group net472, windows-latest
https://github.com/microsoft/agent-framework/actions/runs/29274908654 2026-07-13 merge_group net472, windows-latest
https://github.com/microsoft/agent-framework/actions/runs/29273373355 2026-07-13 merge_group net472, windows-latest

Every occurrence is on the net472 / windows-latest leg of dotnet-test, and every occurrence is a merge_group run. No pull_request occurrences were found in the sample.

Suspected cause

The test races two timers against each other and then asserts which one won by object identity:

https://github.com/microsoft/agent-framework/blob/main/dotnet/tests/Microsoft.Agents.AI.Workflows.UnitTests/InputWaiterTests.cs#L110-L123

Task waitTask = this._waiter.WaitForInputAsync(TimeSpan.FromMilliseconds(300));

Task completed = await Task.WhenAny(waitTask, Task.Delay(TimeSpan.FromSeconds(5)));
completed.Should().BeSameAs(waitTask, "the wait task should complete once the timeout expires");
await waitTask;

WaitForInputAsync(TimeSpan) delegates straight to SemaphoreSlim.WaitAsync(timeout, cancellationToken), so the 300 ms completion is scheduled through the timer queue and then resumed on the thread pool. The assertion only holds if that 300 ms continuation is observed before the 5 s guard fires, which gives the test a fixed wall clock budget of 4.7 s of tolerable scheduling delay.

The net472 integration leg is the slowest and most loaded job in the matrix, so thread pool starvation and GC pauses there can push the 300 ms continuation past the 5 s guard. When that happens Task.Delay wins the WhenAny and BeSameAs fails. This is a test harness timing problem rather than a defect in InputWaiter itself: the semaphore does honor the timeout, the test just cannot guarantee it observes it in time.

Mitigation

A follow up PR quarantines this test with [Fact(Skip = "...")] and links this issue, matching what was done for #5845.

Next steps

  • Remove the wall clock race instead of widening the guard. The assertion does not need to compare task identity at all: awaiting waitTask directly is enough to prove the timeout releases the wait, and a hang would be caught by the test runner timeout rather than by a hand rolled Task.Delay guard.
  • If an explicit bound is still wanted, note that Task.WaitAsync(TimeSpan) is not available on net472, so any replacement has to work on .NET Framework as well.
  • Re-enable the test once the assertion no longer depends on scheduling latency.
[".NET"]

Metadata

Metadata

Assignees

No one assigned

    Labels

    .NETUsage: [Issues, PRs], Target: .Net

    Type

    No type

    Projects

    Status
    No status

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions