powershellpowershell-7.0powershell-7powershell-7.4

Isn't Strict Mode supposed to throw exception when accessing a non-existent key


I am using Set-StrictMode and $ErrorActionPreference

Set-StrictMode -Version Latest
$ErrorActionPreference = "Stop"

$Foo = @{}

$Foo["bar"] # No exception

$Foo.bar # Exception as expected

I am using powershell 7.5.1


Solution

  • This is most likely intentional and is the correct behavior as it aligns with C#:

    Add-Type '
    using System.Collections;
    using System.Collections.Generic;
    
    public static class Test
    {
        public static object TestHash()
        {
            Hashtable hash = new Hashtable();
            return hash["notexist"];
        }
    
        public static object TestDict()
        {
            Dictionary<string, string> dict = new Dictionary<string, string>();
            return dict["notexist"];
        }
    }'
    
    [Test]::TestHash() # no errors, outputs null
    

    You can also read about this in Remarks from Hashtable.Item[object]:

    A key cannot be null, but a value can be. To distinguish between null that is returned because the specified key is not found and null that is returned because the value of the specified key is null, use the Contains method or the ContainsKey method to determine if the key exists in the list.

    Dot notation on a hash table and other IDictionary implementing types is a pure PowerShell implementation, so most likely the reason it throws is because they hadn't taken into account that it shouldn't on a non-existing key.

    However, for Dictionary<TKey, TValue>, which does throw a KeyNotFoundException on non existing keys:

    [Test]::TestDict() # throws, "The given key 'notexist' was not present in the dictionary."
    

    PowerShell on strict mode should probably be throwing too, however it doesn't:

    Set-StrictMode -Version Latest
    
    $dict = [System.Collections.Generic.Dictionary[string, string]]::new()
    $dict['notexist']
    

    And for this case specifically and assuming this isn't the intended behavior, the PowerShell team should be notified. You can submit an issue to their repo if you think this should be fixed in future versions.