Repository navigation
Connect-MgGraph fails after Connect-ExchangeOnline #3394
Description
Describe the bug
I don't know, if this is related to the ExchangeOnlineManagement module (my suspicison) or to Microsoft.Graph, but you should know; too, I guess:
I updated Microsoft.Graph from 2.29.1. to 2.30.0 yesterday and ExchangeOnlineManagement from 3.8.0 to 3.9.0. After the update I found that when I run Connect-ExchangeOnline before Connect-MgGraph, the latter fails with the following error:
Connect-MgGraph: ClientCertificateCredential authentication failed: Method not found: '!0 Microsoft.Identity.Client.BaseAbstractApplicationBuilder`1.WithLogging(Microsoft.IdentityModel.Abstractions.IIdentityLogger, Boolean)'.
When I run Connect-MgGraph first and then Connect-ExchangeOnline, it works.
Expected behavior
IMO it should not matter, which command is run first.
How to reproduce
- On Powershell 7.5.2 ...
- Install Microsoft.Graph 2.30.0
- Install ExchangeOnlineManagement 3.9.0
- First run Connect-ExchangeOnline. ( I used certificate authentication )
- Second run Connect-MgGraph. It does not matter if user or certificate authentication. I tried both
- You should get the error described above
SDK Version
2.30.0
Latest version known to work for scenario above?
2.29.1 together with ExchangeOnlineManagement 3.8.0
Known Workarounds
- First run Connect-MgGraph
- Then run Connect-ExchangeOnline
Debug output
Click to expand log
```DEBUG: ClientCertificateCredential.GetToken invoked. Scopes: [ https://graph.microsoft.com/.default ] ParentRequestId:
DEBUG: ClientCertificateCredential.GetToken was unable to retrieve an access token. Scopes: [ https://graph.microsoft.com/.default ] ParentRequestId: Exception: Azure.Identity.AuthenticationFailedException (0x80131500): ClientCertificateCredential authentication failed: Method not found: '!0 Microsoft.Identity.Client.BaseAbstractApplicationBuilder1.WithLogging(Microsoft.IdentityModel.Abstractions.IIdentityLogger, Boolean)'. ---> System.MissingMethodException (0x80131513): Method not found: '!0 Microsoft.Identity.Client.BaseAbstractApplicationBuilder1.WithLogging(Microsoft.IdentityModel.Abstractions.IIdentityLogger, Boolean)'.
Connect-MgGraph: ClientCertificateCredential authentication failed: Method not found: '!0 Microsoft.Identity.Client.BaseAbstractApplicationBuilder`1.WithLogging(Microsoft.IdentityModel.Abstractions.IIdentityLogger, Boolean)'.
</details>
### Configuration
Name Value
PSVersion 7.5.2
PSEdition Core
GitCommitId 7.5.2
OS Microsoft Windows 10.0.26100
Platform Win32NT
PSCompatibleVersions {1.0, 2.0, 3.0, 4.0…}
PSRemotingProtocolVersion 2.3
SerializationVersion 1.1.0.1
WSManStackVersion 3.0
Architecture: x64
### Other information
_No response_
Activity
SteviebabesUK commentedon Feb 13, 2026
Steve Lee (@SteveL-MSFT) Fascinating read!
What I think those of us out in the field doing basic O365 user management on a day to day basis is for you guys to bang your heads together and stop this happening on an alarmingly regular basis for all of the key modules i.e. MGGraph, ExchangeOnline, PnP & Sharepoint.
FabienTschanz commentedon Mar 5, 2026
And just found that there is another incompatibility with Microsoft Graph 2.35.1 and MicrosoftTeams 7.6.0. Doesn't matter which module is loaded first, if MicrosoftTeams is loaded, then
Connect-MgGraphwill fail:The issue is with the
Microsoft.IdentityModel.Abstractions.dll, where Microsoft.Graph.Authentication uses8.15.0.61118and MicrosoftTeams uses8.14.0.60815.How are we supposed to have a functioning environment if it only takes one single module to be update for nothing to work at the end? It's so frustrating, especially when we PowerShell module authors require several of those Graph, Exchange or Teams modules to be present for our work (looking at you M365DSC). I guess the only way for us to keep working is to spawn a new PowerShell job each time a new module is going to be loaded... Please do something about that.
SamErde commentedon Mar 12, 2026
I just released v1.0 of my DLL Pickle module that prevents most cases of these DLL version conflicts. Please try it out and let me know your results!
marleyhehe commentedon Apr 2, 2026
Still a issue. :@
PimpJuiceIT commentedon Apr 4, 2026
I’m encountering the issue still, even after installing and loading the DLLPickle module.
Here's the detail list of the environment I'm working with:
Priming and connecting to Exchange Online before connecting to Microsoft Graph helps resolve the issue. Currently, I'm testing a V2 script with that as a workaround to get in some of the repetitions on account provisioning operations before updating my main system.
Borgquite commentedon Apr 14, 2026
Fabien Tschanz (@FabienTschanz) I found that when using Windows PowerShell 5.1, ExchangeOnlineManagement plays marginally better with Microsoft.Graph.* 2.36.1 if you downgrade to 3.9.0 instead of 3.9.2, at least in Azure Automation.
Also connect to Exchange Online before Microsoft Graph.
As far as I can see ExchangeOnlineManagement 3.9.2 doesn't appear to include any critical used by Microsoft365DSC so it could be worth downgrading. I wouldn't upgrade the modules until something critical is needed, or Microsoft actually finally resolve this.
PrzemyslawKlys commentedon Jun 3, 2026
While we wait for MS to fix it I've added ALC automated handling to my PowerShell builder
Install-Module PSPublishModuleWhat it does:
Imports the PowerShell commands from those isolated assemblies.
Preserves the module manifest/export surface so users still run normal commands:
This one proves it works also with DllPickle if that's your choice, but it shouldn't be nessecary
v1.2.3: fix Graph sign-in MSAL conflict when Exchange Online connects…
12Knocksinna commentedon Jun 23, 2026
Still problems with Graph SDK V2.38 and Exchange Online Management 3.10. Have protested to the Exchange Online PowerShell team and whined at Gavin Barron (@gavinbarron).
https://office365itpros.com/2026/06/22/powershell-woes-and-cmdlets/
12Knocksinna commentedon Jun 24, 2026
Running Connect-ExchangeOnline -DisableWAM allows Exchange to connect after a Graph connection is established. While you could argue that this fixes the problem, there are tons of customer production scripts in active use today that don't specify DisableWAM and that's the reason why the problem needs to be fixed.
12Knocksinna commentedon Jun 24, 2026
This works with PowerShell 5.1:
Import-Module Microsoft.Graph.Authentication -RequiredVersion 2.38.0
Import-Module ExchangeOnlineManagement -RequiredVersion 3.10.0
Connect-MgGraph
Connect-ExchangeOnline
Again, it's just a workaround that might be acceptable for some but not for organizations that have to update production scripts or who have standardized on PowerShell Core.
tymondouglas commentedon Jul 27, 2026
Will this ever get fixed?
I had to fall back to ExchangeOnlineManagement 3.6.0 for now.
imbaru-design commentedon Aug 26, 2026
this works with zero drama. cheers 🍺
Mike-Crowley commentedon Sep 21, 2026
Confirming this is still present on the current latest: PowerShell 7.6.6, Microsoft.Graph.Authentication 2.40.0, ExchangeOnlineManagement 3.10.1. EXO-then-Graph gives the WithLogging method-not-found; Graph-then-EXO gives the RuntimeBroker NullReferenceException.
One refinement to the version-conflict framing above (e.g. Fabien Tschanz (@FabienTschanz)'s 8.15-vs-8.14 note): I traced the assembly binding, and matching the MSAL versions does not help. Both modules now ship the same Microsoft.Identity.Client (4.83.1) and the same native msalruntime, and it still fails. The break is cross-context type identity, not a version delta:
The practical implication: even a release that perfectly aligned every MSAL version would still break as long as EXO populates Default and Graph falls back into it. More evidence for what gaelcolas (@gaelcolas) and Przemysław Kłys (@PrzemyslawKlys) already said, that EXO needs to load into its own ALC. Until then the isolation wrappers in this thread (DLLPickle, PSPublishModule's Import-IsolatedModule) are the only clean fixes; -DisableWAM sidesteps the Graph-first NullReferenceException but not the WithLogging clash.
SamErde commentedon Sep 21, 2026
Nice summary. Do you have an agent skill that checks to see if open issues are still relevant or have any potential new resolutions?
Mike-Crowley commentedon Sep 21, 2026
No, that was a one-off as a result of trying to work through the mechanics
Mike-Crowley commentedon Sep 25, 2026
On Sep 21 I said the clean fix was EXO loading into its own ALC. #3789 (merged Sep 23; no release contains it yet, v2.40.0 predates the merge) takes the other route: Graph isolates itself. It replaces msgraph-load-context, which had no Load override and fell back to Default, with a GraphAssemblyLoadContext that overrides Load and resolves MSAL, Azure.Identity and Microsoft.IdentityModel.Abstractions from Graph's own folder. Only Microsoft.Graph.Authentication.Core is bridged into Default, and the old AppDomain.AssemblyResolve handler is no longer registered on PS7. Graph can therefore no longer bind to EXO's MSAL in Default, so the WithLogging failure in this issue (EXO-then-Graph) should be gone by construction, and that no longer depends on which MSAL EXO ships (the concern in the Dec 18 comment).
Two caveats. The PR's test pre-loads a stub Microsoft.Identity.Client and connects with -AccessToken, so it verifies the load contexts, not WAM or the WithLogging path. And nothing in the PR exercises Graph-then-EXO (the RuntimeBroker NullReferenceException reported from Feb onward); that direction needs a test build. Windows PowerShell 5.1 keeps the AssemblyResolve approach and is not covered.
Maintainers: worth linking #3789 here alongside #3576, and keeping this open until a release confirms both directions.
svrooij commentedon Sep 25, 2026
Mike Crowley (@Mike-Crowley) eventually it is better if all modules that have dependencies upon Microsoft.Identity.Client (Msal) use a loader principle that looks the same.
robinmalik commentedon Sep 25, 2026
If only. The Exchange team run by their own rules with regard to PowerShell, from everything I've seen over the last 17+ years.
Mike-Crowley commentedon Sep 25, 2026
I built a small harness for this: one fresh pwsh per scenario, a load-state snapshot after every step. PowerShell 7.6.6, Microsoft.Graph.Authentication 2.40.0, ExchangeOnlineManagement 3.10.1, seven scenarios.
Observed, Graph-then-EXO:
EXO-then-Graph still fails (WithLogging MissingMethodException), so neither order works. Two same-session combinations connected: Graph, then Connect-ExchangeOnline -DisableWAM; or Graph via -AccessToken (token from Az.Accounts), then EXO as normal, because Graph never starts msalruntime.
Predictions, no build yet: #3789 fixes EXO-then-Graph by construction; Graph-then-EXO survives it, since EXO's bare-name P/Invokes still find Graph's started copy. Untested fixes: NativeInterop pins P/Invokes to its preloaded handle or tolerates a second startup; Graph uses a Graph-only file name; EXO gets its own load context or DllImportResolver. Related: #3576.
Ask: can the NativeInterop part be routed to the MSAL owners, or should I file it in MSAL.NET?
Harness and report: https://github.com/Mike-Crowley/graph-exo-loadorder
Mike-Crowley commentedon Oct 1, 2026
Microsoft's post today, Action Required: Upgrade ExchangeOnlineManagement PowerShell Module to Version 3.10.1 or Newer, puts an end date on the "stay on an old EXO" workaround: from 31 March 2027, interactive non-WAM sign-in on versions before 3.10.1 may fail. Their FAQ says WAM is not being required, so Graph first, then Connect-ExchangeOnline -DisableWAM (works today on 3.10.1) is not what they are retiring. The path they are hardening is the WAM one, and that is the path this issue breaks.
Mike-Crowley commentedon Oct 19, 2026
Re-ran the harness on the released 2.41.2 (PowerShell 7.6.7, ExchangeOnlineManagement 3.10.1, same nine scenarios, one fresh pwsh each). Every order now connects, including Graph-then-EXO.
Microsoft.Graph.Authenticationload context), so the WithLogging binding never happens.One caveat, reasoning rather than observation: EXO's bare-name binding still decides which runtime EXO runs on after a Graph sign-in. Today that copy is newer than EXO's own; the day EXO ships a newer NativeInterop than Graph, Graph-first puts EXO's interop on an older runtime again. The NativeInterop ask from my earlier comment (pin P/Invokes to the preloaded handle) still looks like the durable fix.
Full report: https://github.com/Mike-Crowley/graph-exo-loadorder/blob/main/report-2.41.2.md
🤖 Claude Mythos 5.1 (max effort) via Claude Code
svrooij commentedon Oct 21, 2026
The way the
AssemblyLoadContextis implemented does not provide a way to load multiple copies of Native binaries. The culprit, the msal broker, is designed to create a singleton that is reachable over a named pipe. And there can only be one running on the machine. If you were to load multiple on the same machine they will fight to respond to that named pipe.What if we fix this issue #3806 and then migrate all the other modules to call the new
Get-MgAccessToken -Scope ...command. Then all the external dependencies to the broker can be removed?Other solution is to always keep the versions equal, but that would require some advanced dependency management combined with synchronized release cycles
Mike-Crowley commentedon Oct 21, 2026
Thanks. Here is what the Oct 19 snapshots show on the two testable parts, with observed and inferred kept apart; one machine, one run per scenario, details in report-2.41.2.md.
On Get-MgAccessToken: Connect-ExchangeOnline has taken an external token since 3.1.0 (-AccessToken), so the route exists in principle. What I do not know is whether the Graph PowerShell client can be issued a token for the Exchange resource at all, and in any case it would cover scripts that opt in, while the default interactive path would still start EXO's own broker, which is where this issue lives. On keeping versions equal: 2.40.0 and EXO 3.10.1 already shared NativeInterop 0.19.4 and MSAL 4.83.1 and still collided, so equal versions are not sufficient on their own; the copy mapped first also has to accept a second startup. That is why a DllImportResolver that pins each module's P/Invokes to the copy it preloaded, in NativeInterop or in EXO, still looks to me like the change that does not depend on anyone's release calendar. If two started copies truly cannot coexist, that moves the fix to MSAL, and the two-live-copies observation above is the one data point I have against it.
🤖 Claude Mythos 5.1 (max effort) via Claude Code
svrooij commentedon Oct 21, 2026
Mike Crowley (@Mike-Crowley) the claude stuff does not really help. I have no clue what the issue is. Maybe I'm just a bit tired at the moment but from what I'm reading PowerShell assembly resolving does not handle native assemblies the same way as managed assemblies. That begs the question, why is this even built in native code 😉 (different team maybe)
Mike-Crowley commentedon Oct 21, 2026
Hey Stephan, sorry about that. I was using Claude to be comprehensive, since I'm sure Microsoft will be using AI as well to read and ingest this work. Here is my understanding, and what I'm proposing:
Your ALC fixed the .NET side. EXO-first works now on 2.41.2. What's left is msalruntime.dll, which is a native DLL, so the ALC doesn't cover it. Graph and EXO each ship their own copy, but Windows finds native DLLs by name. So whoever signs in first, the other module ends up using that first copy. On 2.40 that crashed. On 2.41.2 it still happens, but Graph's newer copy doesn't mind being started twice, so it works. That's luck, not a fix. If EXO ever ships a newer msalruntime than Graph, it could break again.
My proposal: each module should point its msalruntime calls at its own copy. Your ALC already does that for Graph (LoadUnmanagedDll). EXO doesn't. If EXO did the same, or if MSAL's NativeInterop package did it for everyone, load order wouldn't matter anymore. Get-MgAccessToken is still a good idea, but it only helps people who pass a token to EXO. Normal EXO sign-in would still start its own msalruntime.
svrooij commentedon Oct 21, 2026
I want the EXO team to remove the broker completely and make
Microsoft.Graph.Authenticationthe only module that ships the msalclient.Then the exo team can make a dependency upon this module and just call into the Get-MgAccessToken command under the covers
Maybe that last command can even be removed, and every call to exchange would just try to get a token (which will auto cache and refresh if needed)
Mike-Crowley commentedon Oct 21, 2026
I'd like to live in that utopia! But that means SharePoint, Teams, Azure, etc would all need to change their approach, and this multi-decade-old Microsoft org chart meme gives us an idea how that might go: https://assets.sbnation.com/assets/2907963/microsoftguns.jpg