Repository navigation
Closed
Labels
Issue-BugIssue has been identified as a bug in the productIssue has been identified as a bug in the productResolution-FixedThe issue is fixed.The issue is fixed.WG-Enginecore PowerShell engine, interpreter, and runtimecore PowerShell engine, interpreter, and runtimeWG-ReviewedA Working Group has reviewed this and made a recommendationA Working Group has reviewed this and made a recommendation
Description
Prerequisites
- Write a descriptive title.
- Make sure you are able to repro it on the latest released version
- Search the existing issues.
- Refer to the FAQ.
- Refer to Differences between Windows PowerShell 5.1 and PowerShell.
Steps to reproduce
$source = @'
using System.Collections.Specialized;
using System.Management.Automation;
[Cmdlet("Test", "StringCollectionBinding")]
public sealed class TestStringCollectionBindingCommand : PSCmdlet
{
[Parameter(Mandatory = true)]
public StringCollection Value { get; set; }
protected override void ProcessRecord()
{
WriteObject(Value[0]);
}
}
'@
$type = Add-Type -TypeDefinition $source -PassThru
Import-Module -Assembly $type.Assembly
# Select-Object emits one scalar PSObject wrapping a string.
$value = 'test-value' | Select-Object -Unique
$value.GetType().FullName
$value -is [System.Management.Automation.PSObject]
Test-StringCollectionBinding -Value $value
# The control case succeeds:
Test-StringCollectionBinding -Value ([string[]]$value)
# Multiple pipeline results also succeed:
$values = 'first', 'second' | Select-Object -Unique
Test-StringCollectionBinding -Value $valuesExpected behavior
System.String
True
test-valueActual behavior
System.String
True
Test-StringCollectionBinding:
Cannot convert 'expected' to the type
'System.Collections.Specialized.StringCollection' required by parameter
'Value'. Unable to cast object of type
'System.Management.Automation.PSObject' to type 'System.String'.Error details
Exception :
Type : System.Management.Automation.ParameterBindingException
Message : Cannot convert 'test-value' to the type 'System.Collections.Specialized.StringCollection' required by parameter 'Value'. Unable to cast object of type 'System.Management.Automation.PSObject' to type 'System.String'.
ParameterName : Value
ParameterType : [System.Collections.Specialized.StringCollection]
TypeSpecified : [System.Management.Automation.PSObject]
ErrorId : CannotConvertArgument
Line : 22
Offset : 37
CommandInvocation :
MyCommand : Test-StringCollectionBinding
ScriptLineNumber : 22
OffsetInLine : 1
HistoryId : 1
Line : Test-StringCollectionBinding -Value $value 2>$null
Statement : Test-StringCollectionBinding -Value $value 2>$null
PositionMessage : At line:22 char:1
+ Test-StringCollectionBinding -Value $value 2>$null
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
InvocationName : Test-StringCollectionBinding
PipelineLength : 1
PipelinePosition : 1
ErrorRecord :
Exception :
Type : System.Management.Automation.ParentContainsErrorRecordException
Message : Cannot convert 'test-value' to the type 'System.Collections.Specialized.StringCollection' required by parameter 'Value'. Unable to cast object of type 'System.Management.Automation.PSObject' to type 'System.String'.
HResult : -2146233087
CategoryInfo : InvalidArgument: (:) [Test-StringCollectionBinding], ParentContainsErrorRecordException
FullyQualifiedErrorId : CannotConvertArgument,TestStringCollectionBindingCommand
InvocationInfo :
MyCommand : Test-StringCollectionBinding
ScriptLineNumber : 22
OffsetInLine : 37
HistoryId : 1
Line : Test-StringCollectionBinding -Value $value 2>$null
Statement : $value
PositionMessage : At line:22 char:37
+ Test-StringCollectionBinding -Value $value 2>$null
+ ~~~~~~
CommandOrigin : Internal
ScriptStackTrace : at <ScriptBlock>, <No file>: line 22
TargetSite :
Name : EncodeCollection
DeclaringType : [System.Management.Automation.ParameterBinderBase]
MemberType : Method
Module : System.Management.Automation.dll
Data :
System.Management.Automation.Interpreter.InterpretedFrameInfo, System.Management.Automation, Version=7.6.0.500, Culture=neutral, PublicKeyToken=31bf3856ad364e35 : <ScriptBlock>
InnerException :
Type : System.InvalidCastException
TargetSite :
Name : ChkCastAny_NoCacheLookup
DeclaringType : [System.Runtime.CompilerServices.CastHelpers]
MemberType : Method
Module : System.Private.CoreLib.dll
Message : Unable to cast object of type 'System.Management.Automation.PSObject' to type 'System.String'.
Source : System.Private.CoreLib
HResult : -2147467262
StackTrace :
at System.Collections.Specialized.StringCollection.System.Collections.IList.Add(Object value)
at System.Management.Automation.ParameterBinderBase.EncodeCollection(CommandParameterInternal argument, String parameterName, ParameterCollectionTypeInformation collectionTypeInformation, Type toType, Object currentValue, Boolean
coerceElementTypeIfNeeded, Boolean& coercionRequired)
Source : System.Management.Automation
HResult : -2146233087
StackTrace :
at System.Management.Automation.ParameterBinderBase.EncodeCollection(CommandParameterInternal argument, String parameterName, ParameterCollectionTypeInformation collectionTypeInformation, Type toType, Object currentValue, Boolean
coerceElementTypeIfNeeded, Boolean& coercionRequired)
at System.Management.Automation.ParameterBinderBase.CoerceTypeAsNeeded(CommandParameterInternal argument, String parameterName, Type toType, ParameterCollectionTypeInformation collectionTypeInfo, Object currentValue)
at System.Management.Automation.ParameterBinderBase.BindParameter(CommandParameterInternal parameter, CompiledCommandParameter parameterMetadata, ParameterBindingFlags flags)
at System.Management.Automation.CmdletParameterBinderController.BindParameter(CommandParameterInternal argument, MergedCompiledCommandParameter parameter, ParameterBindingFlags flags)
at System.Management.Automation.CmdletParameterBinderController.BindParameter(UInt32 parameterSets, CommandParameterInternal argument, MergedCompiledCommandParameter parameter, ParameterBindingFlags flags)
at System.Management.Automation.CmdletParameterBinderController.BindNamedParameter(UInt32 parameterSets, CommandParameterInternal argument, MergedCompiledCommandParameter parameter)
at System.Management.Automation.ParameterBinderController.BindNamedParameters(UInt32 parameterSets, Collection`1 arguments)
at System.Management.Automation.CmdletParameterBinderController.BindCommandLineParametersNoValidation(Collection`1 arguments)
at System.Management.Automation.CmdletParameterBinderController.BindCommandLineParameters(Collection`1 arguments)
at System.Management.Automation.CommandProcessor.BindCommandLineParameters()
at System.Management.Automation.CommandProcessor.Prepare(IDictionary psDefaultParameterValues)
at System.Management.Automation.CommandProcessorBase.DoPrepare(IDictionary psDefaultParameterValues)
at System.Management.Automation.Internal.PipelineProcessor.Start(Boolean incomingStream)
at System.Management.Automation.Internal.PipelineProcessor.SynchronousExecuteEnumerate(Object input)
--- End of stack trace from previous location ---
at System.Management.Automation.Internal.PipelineProcessor.SynchronousExecuteEnumerate(Object input)
at System.Management.Automation.PipelineOps.InvokePipeline(Object input, Boolean ignoreInput, CommandParameterInternal[][] pipeElements, CommandBaseAst[] pipeElementAsts, CommandRedirection[][] commandRedirections, FunctionContext
funcContext)
at System.Management.Automation.Interpreter.ActionCallInstruction`6.Run(InterpretedFrame frame)
at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedFrame frame)
CategoryInfo : InvalidArgument: (:) [Test-StringCollectionBinding], ParameterBindingException
FullyQualifiedErrorId : CannotConvertArgument,TestStringCollectionBindingCommand
InvocationInfo :
MyCommand : Test-StringCollectionBinding
ScriptLineNumber : 22
OffsetInLine : 37
HistoryId : 1
Line : Test-StringCollectionBinding -Value $value 2>$null
Statement : $value
PositionMessage : At line:22 char:37
+ Test-StringCollectionBinding -Value $value 2>$null
+ ~~~~~~
CommandOrigin : Internal
ScriptStackTrace : at <ScriptBlock>, <No file>: line 22Environment data
Name Value
---- -----
PSVersion 7.6.5
PSEdition Core
GitCommitId 7.6.5
OS Microsoft Windows 10.0.26200
Platform Win32NT
PSRemotingProtocolVersion 2.4
SerializationVersion 1.1.0.1
WSManStackVersion 3.0Visuals
No response
Reacted by Michael Klement
Metadata
Metadata
Assignees
Labels
Issue-BugIssue has been identified as a bug in the productIssue has been identified as a bug in the productResolution-FixedThe issue is fixed.The issue is fixed.WG-Enginecore PowerShell engine, interpreter, and runtimecore PowerShell engine, interpreter, and runtimeWG-ReviewedA Working Group has reviewed this and made a recommendationA Working Group has reviewed this and made a recommendation
Activity
daksh-goyal commentedon Sep 3, 2026
Source analysis
ParameterBinderBase.EncodeCollection()handles list and scalar inputs inconsistently.The list-input branch correctly unwraps each element:
PowerShell/src/System.Management.Automation/engine/ParameterBinderBase.cs
Line 1698 in e5728b6
The scalar-input branch does not unwrap
currentValuebefore callingIList.Add():PowerShell/src/System.Management.Automation/engine/ParameterBinderBase.cs
Line 1852 in e5728b6
Suggested fix
Make the scalar path mirror the list path. When coercion is required, preserve the original wrapped value as the input and assign the converted result to
currentValueElement.SeeminglyScience commentedon Oct 5, 2026
The Engine WG discussed this. We presume this is due to
StringCollectionnot implementingIListand therefore the parameter binder assumes it accepts any type. While we recommend moving away fromStringCollectionif possible, we do agree this should be fixed. Since we cannot determine statically if the list accepts generic objects (when it does not implementIList<>) we recommend special casingStringCollection, that way ETS members are preserved otherwise.