Cannot Convert Value to Type System.String in PowerShell (Fixed)

PowerShell throws “Cannot convert value to type System.String” when an advanced function’s [string] parameter receives an array instead of one value. Call it once per item, or join the items into one string:

foreach ($city in $cities) { Set-Label -City $city }   # one call per item
Set-Label -City ($cities -join ', ')                   # one combined string

In this tutorial, I’ll show you how to reproduce cannot convert value to type system.string, find the hidden array behind it, and choose the right fix in PowerShell 7 and Windows PowerShell 5.1.

What causes Cannot convert value to type System.String?

The error comes from parameter binding. A function with [CmdletBinding()] or a [Parameter()] attribute is an advanced function, and PowerShell won’t squeeze an array into its [string] parameter.

Here’s a tiny function that prints an office label. I passed it two cities:

function Set-Label {
    [CmdletBinding()]
    param([string]$City)
    "Label: $City office"
}

Set-Label -City 'Austin', 'Denver'

Output (PowerShell 7):

Set-Label: C:\psfaqs\err.ps1:7
Line |
   7 |  Set-Label -City 'Austin', 'Denver'
     |                  ~~~~~~~~~~~~~~~~~~
     | Cannot process argument transformation on parameter 'City'. Cannot convert value to type System.String.
PowerShell 7 console showing Cannot process argument transformation on parameter City. Cannot convert value to type System.String
Two cities sent to a [string] parameter of an advanced function (PowerShell 7)

Windows PowerShell 5.1 prints the same message, plus the category InvalidData and the error ID ParameterArgumentTransformationError:

Windows PowerShell 5.1 console showing Cannot convert value to type System.String with ParameterArgumentTransformationError
Same message with CategoryInfo and FullyQualifiedErrorId (Windows PowerShell 5.1)

The parameter name, City, tells you where to look. “Argument transformation” means the value was rejected before your code ran. If simple and advanced functions are new to you, start with functions in PowerShell.

Why does the same call work in a simple function?

Remove [CmdletBinding()] and the call goes through. A simple function converts the array to text and joins the items with a space:

function Set-Label {
    param([string]$City)
    "Label: $City office"
}

Set-Label -City 'Austin', 'Denver'

Output:

Labe