Set-Location fails for paths with special characters when switching drives · Issue #25282 · PowerShell/PowerShell · GitHub
Skip to content

Set-Location fails for paths with special characters when switching drives #25282

Open

Description

@genXdev

Prerequisites

Steps to reproduce

Steps to Reproduce

Use two different, valid and accessible drive letters on your system, I use C: and E:

  1. Create a directory with special characters in its name:
    md "e:\This my test [Folder] with bracket characters"
  2. Navigate into the directory:
    cd 'e:\This my test `[Folder`] with bracket characters\'
  3. Switch to another drive:
    c:
  4. Attempt to switch back to the original directory:
    e:   
    Observed Result: Error:
    Set-Location: Cannot find path 'E:\This my test [Folder] with bracket characters' because it does not exist.
    
  5. Use -LiteralPath when switching back to the original directory:
    cd -LiteralPath e:
    Observed Result:
    Successful navigation to the directory:
    PS E:\This my test [Folder] with bracket characters>
    

Expected behavior

PS C:\> e:
PS E:\This my test [Folder] with bracket characters>

Actual behavior

PS C:\> e:
Set-Location: Cannot find path 'E:\This my test [Folder] with bracket characters' because it does not exist.
PS C:\>

Error details

Exception             :
    Type                 : System.Management.Automation.ItemNotFoundException
    ErrorRecord          :
        Exception             :
            Type    : System.Management.Automation.ParentContainsErrorRecordException
            Message : Cannot find path 'E:\This my test [Folder] with bracket characters'
because it does not exist.
            HResult : -2146233087
        TargetObject          : E:\This my test [Folder] with bracket characters
        CategoryInfo          : ObjectNotFound: (E:\This my test [Fo… bracket
characters:String) [], ParentContainsErrorRecordException
        FullyQualifiedErrorId : PathNotFound
    ItemName             : E:\This my test [Folder] with bracket characters
    SessionStateCategory : Drive
    TargetSite           :
        Name          : SetLocation
        DeclaringType : [System.Management.Automation.SessionStateInternal]
        MemberType    : Method
        Module        : System.Management.Automation.dll
    Message              : Cannot find path 'E:\This my test [Folder] with bracket characters'
because it does not exist.
    Source               : System.Management.Automation
    HResult              : -2146233087
    StackTrace           :
   at System.Management.Automation.SessionStateInternal.SetLocation(String path,
CmdletProviderContext context, Boolean literalPath)
   at Microsoft.PowerShell.Commands.SetLocationCommand.ProcessRecord()
TargetObject          : E:\This my test [Folder] with bracket characters
CategoryInfo          : ObjectNotFound: (E:\This my test [Fo… bracket characters:String)
[Set-Location], ItemNotFoundException
FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.SetLocationCommand
InvocationInfo        :
    MyCommand        : Set-Location
    ScriptLineNumber : 1
    OffsetInLine     : 1
    HistoryId        : 91
    Line             : Set-Location $MyInvocation.MyCommand.Name
    Statement        : Set-Location $MyInvocation.MyCommand.Name
    PositionMessage  : At line:1 char:1
                       + Set-Location $MyInvocation.MyCommand.Name
                       + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    InvocationName   : Set-Location
    CommandOrigin    : Internal
ScriptStackTrace      : at <ScriptBlock>, <No file>: line 1
                        at <ScriptBlock>, <No file>: line 1
PipelineIterationInfo :
      0
      1

Environment data

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

Visuals

No response

Activity

  1. genXdev commented on Apr 5, 2025

    @genXdev
    Author

    Additional Observation: Resolve-Path cmdlet with -RelativeBasePath parameter

    I have discovered a similar issue affecting the Resolve-Path cmdlet when using the -RelativeBasePath parameter along with -Relative for paths containing special characters like [ and ].

    Steps to Reproduce:

    1. Create a directory with special characters in its name:

      PS C:\>md "E:\This my test [Folder] with bracket characters"
    2. Create a test file in the directory:

      PS C:\>New-Item -Path 'E:\This my test [Folder] with bracket characters\file-1.txt' -ItemType File
    3. Navigate to the directory:

      PS C:\>cd 'E:\This my test `[Folder`] with bracket characters\'
    4. Resolve the full path of the test file:

      PS E:\This my test [Folder] with bracket characters>Resolve-Path -LiteralPath 'E:\This my test [Folder] with bracket characters\file-1.txt'

      Observed Result:

      Path
      ----
      E:\This my test [Folder] with bracket characters\file-1.txt
      
    5. Attempt to resolve the relative path using -Relative and -RelativeBasePath:

      PS E:\This my test [Folder] with bracket characters>Resolve-Path -LiteralPath 'E:\This my test [Folder] with bracket characters\file-1.txt' -Relative -RelativeBasePath .\

      Observed Result:

      Resolve-Path: Cannot find path 'E:\This my test [Folder] with bracket characters' because it does not exist.
      

    Analysis:

    This issue shows that the Resolve-Path cmdlet does not handle paths containing special characters like [ and ] correctly when using both -Relative and -RelativeBasePath. This behavior is similar to the previously reported issue with the Set-Location cmdlet. It indicates potential inconsistencies in how these parameters interpret or handle paths with special characters.

  2. 237dmitry commented on Apr 5, 2025

    @237dmitry
    1. Attempt to resolve the relative path using -Relative and -RelativeBasePath

    What is the current path from where you are trying to resolve the file path? Is it part of this file system tree?

  3. genXdev commented on Apr 5, 2025

    @genXdev
    Author

    237dmitry

    The current path from where to resolve the file path would be:
    'E:\This my test [Folder] with bracket characters\file-1.txt'

    I'll edit the reproduction steps to include the 'PS E:\This my test [Folder] with bracket characters>' prompt.

  4. TobiasPSP commented on Apr 16, 2025

    @TobiasPSP
    Collaborator

    When you switch to a different drive by entering the drive name, PS internally runs a function:

    PS> $function:c:
    Set-Location $MyInvocation.MyCommand.Name
    

    This function uses positional arguments so the default -Path is used, and the current path is treated like a wildcard path: the brackets in the path aren't taken literally but get resolved. The resulting path obviously does not exist.

    A solution would be to use named arguments and change the function so that it explicitly uses -LiteralPath:

    Set-Location -LiteralPath $MyInvocation.MyCommand.Name
    

    This would make a lot of sense since $MyInvocation.MyCommand.Name is always a literal path and never a wildcard expression (unless I am overlooking something).

    This case also serves as a reminder that with all filesystem-related cmdlets, -LiteralPath is the better choice in the majority of cases, and the (default - sic!) -Path must only be used if you are really intending to resolve wildcards.

    That said, in this case, while you could redefine the functions to fix the problem, they should be corrected by core.

  5. moved this from Queue to In-Progress-Issues in Cmdlets Working Groupon May 7, 2025
  6. moved this from In-Progress-Issues to Reviewed in Cmdlets Working Groupon May 7, 2025
  7. TobiasPSP commented on May 7, 2025

    @TobiasPSP
    Collaborator

    The cmdlet WG reviewed this. This is a bug, and -LiteralPath should be added to Set-Location in the automatically defined drive-letter functions.

  8. added
    Up-for-GrabsUp-for-grabs issues are not high priorities, and may be opportunities for external contributors
    WG-ReviewedA Working Group has reviewed this and made a recommendation
    Issue-BugIssue has been identified as a bug in the product
    and removed
    Needs-TriageThe issue is new and needs to be triaged by a work group.
    on May 7, 2025
  9. iSazonov commented on May 13, 2025

    @iSazonov
    Collaborator

    There already was such conclusion #12294 (comment)

  10. iSazonov commented on May 13, 2025

    @iSazonov
    Collaborator

    For reference #20701

  11. added a commit that references this issue on Nov 22, 2025
    74caef9
  12. yotsuda commented on Nov 27, 2025

    @yotsuda
    Contributor

    I attempted to implement the fix as WG proposed - modifying the SetDriveScriptBlock (embedded functions like function:C:).

    Here is the diff I tried:

    diff --git a/src/System.Management.Automation/engine/InitialSessionState.cs b/src/System.Management.Automation/engine/InitialSessionState.cs
    index 62308282d..b6d7092e4 100644
    --- a/src/System.Management.Automation/engine/InitialSessionState.cs
    +++ b/src/System.Management.Automation/engine/InitialSessionState.cs
    @@ -4889,7 +4889,7 @@ end {
     # .ExternalHelp System.Management.Automation.dll-help.xml
     ";
    
    -        internal const string DefaultSetDriveFunctionText = "Set-Location $MyInvocation.MyCommand.Name";
    +        internal const string DefaultSetDriveFunctionText = "Set-Location -LiteralPath $MyInvocation.MyCommand.Name";
    
             internal static readonly ScriptBlock SetDriveScriptBlock = ScriptBlock.CreateDelayParsedScriptBlock(DefaultSetDriveFunctionText, isProductCode: true);

    However, I found that this change alone does not fix the issue. The drive-switching syntax (e.g., E:) does not go through these drive functions. Instead, it is processed directly in SessionStateLocationAPIs.SetLocation(), where CurrentDrive.CurrentLocation is combined with the drive name and then passed through wildcard expansion.

    The actual code path is:

    1. User types E:
    2. SessionStateLocationAPIs.SetLocation() is called
    3. At line 309-312, the path is constructed from CurrentDrive.CurrentLocation
    4. This path is then passed to Globber.GetGlobbedMonadPathsFromMonadPath() which performs wildcard expansion
    5. Brackets in the path are interpreted as wildcard patterns, causing the error

    Therefore, the fix in my previous PR #26510 (modifying SessionStateLocationAPIs.cs to suppress wildcard expansion for paths restored from drive's CurrentLocation) appears to be necessary to resolve this issue.

    Ilya (@iSazonov) Should I resubmit the approach from PR #26510, or is there an alternative direction WG would prefer?

  13. iSazonov commented on Nov 28, 2025

    @iSazonov
    Collaborator

    I see the same approach in #25282. If this doesn't work I afraid there is more fundamental problem or problems we need to investigate. Perhaps root of the issue is that we extract an already processed path and re-process it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Area-FileSystem-Providerspecific to the FileSystem providerIssue-BugIssue has been identified as a bug in the productKeepOpenThe bot will ignore these and not auto-closeUp-for-GrabsUp-for-grabs issues are not high priorities, and may be opportunities for external contributorsWG-Cmdletsgeneral cmdlet issuesWG-ReviewedA Working Group has reviewed this and made a recommendation

    Type

    No type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions