Skip to content

Set-Variable unexpectedly mutates variables even when -Option Constant results in an error #27679

Description

@dkontyko

Prerequisites

This bug relates to a variable being changed even when an error results from -Option Constant being included in the Set-Variable call. I found 3 variations of this bug.

1. Writable variable is mutated even though an error results

& {
    New-Variable -Name x -Value 1

    Set-Variable -Name x -Value 2 -Option Constant `
        -ErrorVariable setError

    Get-Variable -Name x |
        Select-Object Name, Value, Options

    $setError.FullyQualifiedErrorId
}

Error Message:

Set-Variable:
Line |
   4 |      Set-Variable -Name x -Value 2 -Option Constant `
     |      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     | Existing variable x cannot be made constant. Variables can be made constant only at creation time.

Expected:

Name    Value    Options
----    -----    -------
x       1        None
VariableCannotBeMadeConstant,Microsoft.PowerShell.Commands.SetVariableCommand

Actual:

Name    Value    Options
----    -----    -------
x       2        None
VariableCannotBeMadeConstant,Microsoft.PowerShell.Commands.SetVariableCommand

2. ReadOnly variable is mutated and ReadOnly option removed even though an error results

& {
    New-Variable -Name x -Value 1 -Option ReadOnly

    Set-Variable -Name x -Value 2 -Force -Option Constant `
        -ErrorVariable setError

    Get-Variable -Name x |
        Select-Object Name, Value, Options

    $setError.FullyQualifiedErrorId
}

Expected:

Name    Value    Options
----    -----    -------
x       1        ReadOnly
VariableCannotBeMadeConstant,Microsoft.PowerShell.Commands.SetVariableCommand

Actual:

Name    Value    Options
----    -----    -------
x       2        None
VariableCannotBeMadeConstant,Microsoft.PowerShell.Commands.SetVariableCommand

3. ReadOnly option is removed even though an error results

& {
    New-Variable -Name x -Value 1 -Option ReadOnly

    Set-Variable -Name x -Force -Option Constant `
        -ErrorVariable setError

    Get-Variable -Name x |
        Select-Object Name, Value, Options

    $setError.FullyQualifiedErrorId
}

Expected:

Name    Value    Options
----    -----    -------
x       1        ReadOnly
VariableCannotBeMadeConstant,Microsoft.PowerShell.Commands.SetVariableCommand

Actual:

Name    Value    Options
----    -----    -------
x       1        None
VariableCannotBeMadeConstant,Microsoft.PowerShell.Commands.SetVariableCommand

I could see a rationale for still mutating the variables in the first two cases, although I couldn't find any documentation to indicate that's intended behavior. However, even if that's the case, removing the ReadOnly option in the latter two variations seems contrary to the user's intended outcome, even if -Option Constant is correct to result in an error.

I can propose a PR to fix this, but I wanted to clarify the official intended behavior first.

Environment data

Name                           Value
----                           -----
PSVersion                      7.6.3
PSEdition                      Core
GitCommitId                    7.6.3
OS                             Microsoft Windows 10.0.26220
Platform                       Win32NT
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0…}
PSRemotingProtocolVersion      2.4
SerializationVersion           1.1.0.1
WSManStackVersion              3.0

Metadata

Metadata

Assignees

No one assigned

    Labels

    Needs-TriageThe issue is new and needs to be triaged by a work group.WG-Cmdletsgeneral cmdlet issuesWG-NeedsReviewNeeds a review by the labeled Working Group

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions