You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Changing Azure DevOps credentials disposes the VssConnection that in-flight requests are still using #298
CredentialedSessionCache.Get() (BuildMonitor/Providers/CredentialedSessionCache.cs:75, called from AzureDevOps.cs:89) handles changed credentials by calling Invalidate(), which disposes the previous session (VssConnection) immediately.
Callers that already got that session keep it across the rate-limit delay and the HTTP call, and up to 5 requests can be in flight at once. The class remarks say a rebuild "does not disturb a request already in flight", but disposing the session does exactly that.
Why it matters
In-flight calls fail with ObjectDisposedException.
MakeAzureDevOpsRequestAsync only catches Vss* exceptions and HttpRequestException, so the ObjectDisposedException escapes and faults the update loop.
The Set Credentials flow changes AccountId and then Token in two separate popups, so it triggers two rebuilds while polling continues. This is the ordinary path for re-entering a PAT, not a rare race.
The existing test ASessionHandedToACallerSurvivesARebuildBehindIt only reads a string off the fake session, so it never checks disposal.
Reproduction (ran)
Get("org", "pat1"), keep the result.
Get("org", "pat2").
Result: the first session reports Disposed == true while its holder may still be using it.
Suggested fix / acceptance criteria
Either lease sessions with a reference count and dispose a replaced session only when its last holder releases it, or defer disposal of replaced sessions.
At minimum, have MakeAzureDevOpsRequestAsync catch ObjectDisposedException and retry once with a fresh session.
Extend the existing test to assert that the session handed out earlier is not disposed while it is held.
Next steps: Lease sessions with a reference count, or defer disposing a session once it is replaced. At minimum, catch ObjectDisposedException and retry once with a fresh session. Extend ASessionHandedToACallerSurvivesARebuildBehindIt to assert the held session is not disposed.
Activity
matt-edmondson commentedon Sep 26, 2026
Triage
ObjectDisposedExceptionfaults the update loop. It is transient: the next cycle gets a fresh session. It gets worse while One persistent GitHub 5xx makes the app re-run discovery and re-poll back-to-back instead of on its interval #299 is open.CredentialedSessionCache.Get/InvalidateandMakeAzureDevOpsRequestAsync. Maintainer: @matt-edmondson.WhenAllconsequence.ObjectDisposedExceptionand retry once with a fresh session. ExtendASessionHandedToACallerSurvivesARebuildBehindItto assert the held session is not disposed.Generated by Claude Code