Skip to content

Extensions.AspNetCore.Tests: flaky ObjectDisposedException from UseInboxHandler<T> static logger #4565

Closed

Description

@iancooper

Symptom

tests/Paramore.Brighter.Extensions.AspNetCore.Tests fails intermittently. Each failing run loses 1–6 tests, and a rerun often passes 65/65. These tests fail most often:

  • RequestScopeRegistrationEntryPointTests.When_add_consumers_func_alone_calls_the_extension_the_affinity_should_reach_the_options_and_adoption_should_work
  • RequestScopeRegistrationEntryPointTests.When_add_consumers_action_alone_calls_the_extension_the_affinity_should_reach_the_options_and_adoption_should_work
  • RequestScopeRegistrationEntryPointTests.When_add_consumers_func_already_sets_join_ambient_the_extensions_always_new_should_still_win
  • RequestScopeRegistrationEntryPointTests.When_add_consumers_action_already_sets_join_ambient_the_extensions_always_new_should_still_win
  • PackageReferencedButExtensionNotCalledTests.When_the_package_is_referenced_but_the_extension_is_not_called_the_accessor_should_not_be_touched (fails with ConfigurationException: Error when building pipeline)
System.TypeInitializationException : The type initializer for 'Paramore.Brighter.Inbox.Handlers.UseInboxHandler`1' threw an exception.
---- System.ObjectDisposedException : Cannot access a disposed object.

Reproduced on unmodified master (f2b93125a): of three runs on each of net9.0 and net10.0, one passed, and the other two failed 3–5 tests per framework.

Cause

This is the race that tests/Paramore.Brighter.Extensions.AspNetCore.Tests/Initializer.cs already describes in its remarks:

  1. Each PlaceOrderWebApplicationFactory host reassigns ApplicationLogging.LoggerFactory to its own ILoggerFactory, then disposes that factory when the test ends.
  2. A closed generic Brighter type initialises its static ILogger once, on first touch, against whatever factory the property holds at that moment.
  3. If that is a factory a finished test has already disposed, the type initializer throws ObjectDisposedException.

The [ModuleInitializer] avoids this by warming every closed type the tests use. It has 52 RunClassConstructor calls, but none for UseInboxHandler<T>. The consumer pipelines in these tests add that handler implicitly, so its closed types are first touched at whatever moment a test happens to build one.

Suggested fix

In Initializer.Initialize(), add RuntimeHelpers.RunClassConstructor(typeof(UseInboxHandler<T>).TypeHandle) for each request type whose consumer pipeline gets the inbox handler, and the async variant too if those pipelines use it. Then check for any other implicitly added handler types that are also missing.

Found while verifying #4562.

Activity

  1. added
    MaintenanceBuild, CI, refactoring, testing infrastructure, and other chores
    .NETPull requests that update .net code
    and removed on Oct 9, 2026
  2. self-assigned this
    on Oct 9, 2026
  3. added a commit that references this issue on Oct 11, 2026
    e10a477
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

.NETPull requests that update .net code3 - DoneBugMaintenanceBuild, CI, refactoring, testing infrastructure, and other choresV10.X

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions