Alexander Frank
Back to notes
  • Microsoft Graph
  • PowerShell
  • Entra ID

Why Update-MgUser fails when you disable an account

A one-liner from offboarding that does not run, and what the error message reveals about the Graph PowerShell SDK.

5 min read

It is the least spectacular step in the whole offboarding process: disable an account. One attribute, one value, done. In the JML lab I typed it the way anyone would type it:

Update-MgUser -UserId $id -AccountEnabled $false

And got back: “A positional parameter cannot be found that accepts argument 'False'.” No permission error, no hint about a missing scope. A parser message — so nothing had even been sent to Graph yet.

What the message is actually saying

“Positional parameter cannot be found” is one of the most unambiguous errors PowerShell produces. It means there was one argument too many, no named parameter was left to take it, and it did not fit any position either. Applied to the one-liner: PowerShell handled -AccountEnabled, finished with it, and was then left holding $false with nowhere to put it.

That happens precisely when a parameter is not a value parameter but a switch. A switch does not take its value from the next token; its mere presence means true. The $false that follows is then no longer a value but an orphaned argument.

You can verify this against your own module version with a single line:

(Get-Command Update-MgUser).Parameters['AccountEnabled'].ParameterType

Two ways that work

The first is colon syntax. It is the official way to assign a value to a switch explicitly, and it is valid everywhere in PowerShell, not just here:

Update-MgUser -UserId $id -AccountEnabled:$false

The second bypasses parameter binding and sends the request body directly — exactly the way the Graph API expects it anyway:

Update-MgUser -UserId $id -BodyParameter @{ AccountEnabled = $false }

In scripts I now use the second variant throughout. Not because the first is wrong, but because it has a property that is easy to overlook: a single forgotten colon inverts the result. -AccountEnabled $false at least fails loudly. -AccountEnabled on its own — after a hasty refactor, say — runs through happily and enables the account that was supposed to be disabled. An offboarding script that silently does the opposite is considerably worse than one that stops.

Where this comes from

The Microsoft.Graph module is not hand-written. It is generated from the OpenAPI description of the Graph API. What you have in front of you in the console is a machine translation of a REST endpoint into cmdlet form. That translation is convenient in many places. In a few, it is not quite one to one.

In practice that means three things. First, the Graph documentation for the request body is always a more reliable source than the cmdlet signature. Second, generated signatures can change between module versions, which is why Get-Command is faster than a search engine when you are debugging. Third, -BodyParameter is not an emergency exit but the more direct route: a hashtable that maps one to one onto the JSON that goes over the wire regardless.

The whole thing cost me maybe twenty minutes. I still think it is worth writing down, because no course tells you that a boolean in the generated SDK can be a switch. You learn that by typing it yourself and running into it.

A question about identity or endpoint management?

Write me a line about what it is about. I usually reply within one working day.

info@alexander-frank.org

Remote, German business hours. Project-based, not employment.