Skip to content

Surface app startup exceptions after the host is disposed in WebApplicationFactory - #69685

Open
Demivan wants to merge 1 commit into
dotnet:mainfrom
Demivan:fix/deferredhost-disposed-start
Open

Demivan wants to merge 1 commit into
dotnet:mainfrom
Demivan:fix/deferredhost-disposed-start

Conversation

@Demivan

@Demivan Demivan commented Oct 6, 2026

Copy link
Copy Markdown
  • You've read the Contributor Guide and Code of Conduct.
  • You've included unit or integration tests for your change, where applicable.
  • You've included inline docs for your change, where applicable.
  • There's an open issue for the PR that you are making. If you'd like to propose a new feature or change, please open an issue to discuss the change or find an existing issue.

Rethrow the app's startup exception instead of ObjectDisposedException

Description

When the app under test fails in IHost.StartAsync, app.Run() disposes the host before the entry point exits. If that happens before DeferredHost.StartAsync resolves IHostApplicationLifetime, WebApplicationFactory throws ObjectDisposedException and the real startup exception is lost.

DeferredHost.StartAsync now skips the ApplicationStarted registration when the host is already disposed and keeps awaiting the start TCS. The entry point is exiting at that point, and HostFactoryResolver reports its completion in a finally, so EntryPointCompleted always completes the TCS with the app's exception or result. The success and cancellation paths are unchanged.

The regression test uses SimpleWebSiteWithWebApplicationBuilder with a failing ValidateOnStart. Its factory holds CreateHost until the app's service provider has been disposed, which makes the ordering deterministic. Without the fix it failed 10/10 runs with the reported ObjectDisposedException stack. With the fix it passed 10/10, and Mvc.FunctionalTests passes in full (1669 passed, 3 skipped).

Fixes #69684

🤖 Generated with Claude Code

@github-actions github-actions Bot added the area-mvc Includes: MVC, Actions and Controllers, Localization, CORS, most templates label Oct 6, 2026
@dotnet-policy-service dotnet-policy-service Bot added the community-contribution Indicates that the PR has been added by a community member label Oct 6, 2026
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Thanks for your PR, @Demivan. Someone from the team will get assigned to your PR shortly and we'll get it reviewed.

@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Looks like this PR hasn't been active for some time and the codebase could have been changed in the meantime.
To make sure no conflicting changes have occurred, please rerun validation before merging. You can do this by leaving an /azp run comment here (requires commit rights), or by simply closing and reopening.

@dotnet-policy-service dotnet-policy-service Bot added the pending-ci-rerun When assigned to a PR indicates that the CI checks should be rerun label Oct 14, 2026
When the app under test fails in IHost.StartAsync, app.Run() disposes
the host before the entry point exits and reports the exception through
EntryPointCompleted. If the disposal won the race with
DeferredHost.StartAsync resolving IHostApplicationLifetime, the factory
threw ObjectDisposedException and the real startup exception was lost.

Skip the ApplicationStarted registration when the host is already
disposed and keep awaiting the start TCS. HostFactoryResolver reports
entry point completion in a finally, so the TCS always completes with
the app's exception or result.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Demivan
Demivan force-pushed the fix/deferredhost-disposed-start branch from f8ec6e4 to ffcee02 Compare October 17, 2026 16:32

This branch has not been deployed

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

Labels

area-mvc Includes: MVC, Actions and Controllers, Localization, CORS, most templates community-contribution Indicates that the PR has been added by a community member pending-ci-rerun When assigned to a PR indicates that the CI checks should be rerun

Projects

None yet

Development

Successfully merging this pull request may close these issues.

WebApplicationFactory sometimes throws ObjectDisposedException instead of the app's startup exception

1 participant