Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cannot bind argument to parameter '' because it is null

I have this strange observation and I don't know how to cope with this:

I'm reading a list of files from a directory. I pipe these through a sequence of Select-Object, Sort-Object, Select-Object calls in order to retrieve just a single property. Finally, I feed the result to a pipe.

Now, when Get-ChildItem retrieves no files, I get the error message: Cannot bind argument to parameter 'File' because it is null.

Here's an MRE:

function Test
{
  [CmdletBinding()]
  param
  (
    [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)]$File
  )
  process { }
}


$arr = (Get-ChildItem -Filter '*.xxxx' |
    Select-Object -Property 'Name',
    @{
      name = 'FileObject'
      expression = { $_ }
    } |
    Sort-Object -Property 'Name').FileObject


$arr | Test

(Please note: this is just an MRE, not a meaningful piece of code. Don't focus on the Select-Object expression.)


When I change the last line to: Sort-Object -Property 'Name') by removing the .FileObject, everything runs flawlessly.

An empty array is an empty array, I guess. In both cases, $arr -eq $null is $true. So, why do I get different behaviour? How can I make this run flawlessly (and still being strict) with the FileObject property still being the return type?

like image 410
AxD Avatar asked Feb 02 '26 06:02

AxD


1 Answers

There is a difference between $null and AutomationNull.Value. When Cmdlets, Functions and Script Blocks return nothing what you actually get is this type of null value but then by expanding on the .FileObject property when the statement returned Automation.Value you're effectively getting $null instead.

If you try to access a property or sub property of an object that doesn't have the specified property, you get a $null value like you would for an undefined variable. It doesn't matter if the variable is $null or an actual object in this case.

See Everything you wanted to know about $null for more details.

$var1 = $null
$var2 = & { }

function Test {
    [CmdletBinding()]
    param
    (
        [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)]$File
    )
    begin { 'begin' }
    process { 'process' }
    end { 'end' }
}

$var1 | Test # fails on `process` block
$var2 | Test # only `begin` and `end` are called, no items are bound from pipeline
$var2.SomProperty | Test # now is `$null`, thus same issue as first example
like image 118
Santiago Squarzon Avatar answered Feb 03 '26 19:02

Santiago Squarzon



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!