Skip to content

The GH-3521 application-assembly warning has a hole on one path and fires on healthy hosts on the other #3778

Description

@jeremydmiller

The GH-3521 divergence warning is meant to make a silent first-host-wins application-assembly pin observable, so that a "No routes can be determined" mystery has a breadcrumb. In its current form it does neither reliably: one path can never warn, and the other warns almost always.

This is the Wolverine-side twin of JasperFx/jasperfx#601. Surfaced while diagnosing #3776, where both defects actively pushed the investigation the wrong way.

1. The RememberedApplicationAssembly path cannot warn

WolverineOptions.Assemblies.cs:112-127:

else if (RememberedApplicationAssembly != null)
{
    ApplicationAssembly = RememberedApplicationAssembly;   // adopts a process-wide pin, silently
}

This adopts an assembly pinned by whichever host started first in the process — exactly the situation the warning exists for — and never calls CheckForDivergentApplicationAssembly. Only the jasperfx.ApplicationAssembly path in ReadJasperFxOptions does.

JasperFx's equivalent already gets this right (JasperFxOptions.cs:171 calls checkForDivergentApplicationAssembly in the same branch), so this looks like a straightforward omission rather than a deliberate difference.

2. On the other path it fires on healthy hosts

Instrumenting a fully green local run of the CIPolecat shard: RegistrationCallingAssembly resolved to Wolverine.SqlServer on 81 of 82 hosts, not to PolecatTests which actually called UseWolverine. The adopted assembly was correctly PolecatTests, so the comparison found a mismatch and raised the warning on all 81 — on a run where nothing was wrong at all.

The cause is determineCallingAssembly (via CaptureRegistrationCallingAssembly): when a Wolverine extension registers on the application's behalf, the first non-System*/Microsoft* frame outside Wolverine belongs to the extension.

Why this is worth fixing rather than tolerating

On #3776 I recorded "zero occurrences of the warning in the failing logs" as grounds for ruling out an application-assembly problem. That was precisely the bug — discovery was scanning xunit.v3.core. The reasoning was void twice over: defect 1 meant that path could not have warned, and defect 2 means a healthy run is full of warnings anyway, so neither presence nor absence carries information.

A diagnostic that cannot be reasoned from in either direction is worse than none, because it invites exactly this mistake.

Suggested direction

  • Call CheckForDivergentApplicationAssembly in the RememberedApplicationAssembly branch, matching JasperFx.
  • Make RegistrationCallingAssembly mean what its name says before relying on it for the comparison — either by skipping Wolverine's own extension assemblies in the walk, or by capturing the registering assembly at the outermost public entry point rather than re-deriving it deep in the registration path.
  • Failing that, narrow the trigger so it only fires where the resolution is actually known to be unreliable, rather than on every name mismatch.

Related: #3776, #3777 (which adds IsTestRunnerAssembly and could supply part of the filtering), JasperFx/jasperfx#600, JasperFx/jasperfx#601.

🤖 Generated with Claude Code

https://claude.ai/code/session_013eR4GL278688VhyhrGcttJ

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions