Remove-Item removes the symbolic links and junctions when used with -WhatIf parameter · Issue #16664 · PowerShell/PowerShell · GitHub
Skip to content

Remove-Item removes the symbolic links and junctions when used with -WhatIf parameter #16664

Open

Description

@Tospaa

Prerequisites

Steps to reproduce

  • Create a new junction (reparse point) of an arbitrary directory
New-Item -Path junction -ItemType Junction -Value 'C:\Program Files\'
  • Create a new symbolic link of an arbitrary directory
New-Item -Path symlink -ItemType SymbolicLink -Value 'C:\Program Files\'
  • Run the Remove-Item command with the -WhatIf switch parameter
Remove-Item -Path .\junction\ -WhatIf
Remove-Item -Path .\symlink\ -WhatIf

Expected behavior

Should not remove junction or symbolic link

Actual behavior

Removes the junction and symbolic link

Error details

No response

Environment data

PS C:\Users\tospaa> $PSVersionTable

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

Visuals

2021-12-22.10-43-06.mp4

Activity

  1. God-damnit-all commented on Feb 10, 2022

    @God-damnit-all
    Contributor

    I can confirm. This just ruined my day.

  2. darthwalsh commented on Jul 6, 2023

    @darthwalsh

    #19714 seems to be the same issue. (probably best to close one as a dupe?)

  3. msftrncs commented on Jul 10, 2023

    @msftrncs
    Contributor

    James O'Neill (@jhoneill), the conversation appears to have moved to this older thread that didn't turn up when originally researching my issue.

  4. ViperTG commented on Aug 9, 2023

    @ViperTG

    Can confirm this is still an issue in 7.3.6, just had it delete my links while testing .. very annoying.

  5. msftrncs commented on Sep 27, 2023

    @msftrncs
    Contributor

    ViperTG, still an issue, until this issue is closed. James O'Neill (@jhoneill) had at least marked #19714 as a bug.

  6. jhoneill commented on Sep 27, 2023

    @jhoneill

    Carl Morris (@msftrncs) I now longer have any influence to get items looked at having been removed from the working group.

  7. God-damnit-all commented on Sep 28, 2023

    @God-damnit-all
    Contributor

    Carl Morris (@msftrncs) I now longer have any influence to get items looked at having been removed from the working group.

    Sorry to hear that. Interpersonal issues?

  8. jhoneill commented on Sep 28, 2023

    @jhoneill

    Carl Morris (@msftrncs) I now longer have any influence to get items looked at having been removed from the working group.

    Sorry to hear that. Interpersonal issues?

    I got suspended on here for arguing with someone and categorising their behaviour over a long period as that of a troll. My access to the working group - and that of another member who'd be on the same side of the argument - vanished later without a word. Characterize that as you will.

  9. God-damnit-all commented on Sep 28, 2023

    @God-damnit-all
    Contributor

    Carl Morris (@msftrncs) I now longer have any influence to get items looked at having been removed from the working group.

    Sorry to hear that. Interpersonal issues?

    I got suspended on here for arguing with someone and categorising their behaviour over a long period as that of a troll. My access to the working group - and that of another member who'd be on the same side of the argument - vanished later without a word. Characterize that as you will.

    Here's hoping that your explanation here doesn't meet the same fate.

  10. God-damnit-all commented on Nov 5, 2023

    @God-damnit-all
    Contributor

    I feel like I should point out that while not a lot of Windows users are going to run into this, this is potentially ruinous on a Linux system.

  11. jhoneill commented on Nov 10, 2023

    @jhoneill

    @ImportTaste There seems to a small flurry of issues around the behaviour of Remove-Item, not always honouring -whatif is one, -filter and -recurse interacting in a way that is probably just wrong, but definitely counter-intuitive, and not having the same dynamic parameters as Get-ChildItem (like -file and -directory)

    Someone more optimistic than I am might look to all these to be bundled up and addressed together.

  12. MatejKafka commented on May 15, 2024

    @MatejKafka
    Contributor

    The issue seems specific to directory reparse points. For file symlinks, it works as expected.

    $null = mkdir dir
    $null = ni file.txt
    
    $null = ni -Type SymbolicLink filelink.txt -Target .\file.txt
    $null = ni -Type SymbolicLink dirlink -Target .\dir
    
    ls
    rm .\filelink.txt -WhatIf
    rm .\dirlink -WhatIf
    ls
  13. MatejKafka commented on May 15, 2024

    @MatejKafka
    Contributor

    The issue is here:

    I don't have time to champion a PR, Justin Grote (@JustinGrote) said he might go for it.

    Seems it was always somewhat broken, but this issue was exposed in f1769fe

  14. VirgilMing commented on Jul 30, 2026

    @VirgilMing

    Disclaimer: This comment is mostly written by Codex/ChatGPT. I'm not exactly sure of the code review part, but I really observed the real world behavior.

    Confirmed that this is still reproducible in PowerShell 7.6.4.

    Environment

    PSVersion       7.6.4
    PSEdition       Core
    GitCommitId     7.6.4
    OS              Windows 11 Pro for Workstations, build 26200, x64
    

    Observed real-world behavior

    During debugging with tooling that manages an NTFS junction, I deliberately used -WhatIf to preview the operation, with no intent of modifying the link:

    Test-Path -LiteralPath $junction
    # output: True
    
    Remove-Item -LiteralPath $junction -Recurse -Force -WhatIf -ErrorAction Stop
    
    Test-Path -LiteralPath $junction
    # output: False
    
    Test-Path -LiteralPath $target
    # output: True

    PowerShell specifically printed:

    What if: Performing the operation "Remove Directory" on target "<junction>".
    

    The invocation completed without error, but the junction itself was detached despite -WhatIf. The target directory and its contents remained intact.

    This is particularly dangerous in recovery and diagnostic tooling, where -WhatIf is relied upon as the dry-run safety boundary before a destructive filesystem operation.

    Source-level cause in v7.6.4

    The source-level cause previously identified in this thread remains present in v7.6.4:

    https://github.com/PowerShell/PowerShell/blob/v7.6.4/src/System.Management.Automation/namespaces/FileSystemProvider.cs#L3035-L3080

    RemoveDirectoryInfoItem() stores the result of ShouldProcess() in continueRemoval:

    continueRemoval = ShouldProcess(directory.FullName, action);

    However, the reparse-point/name-surrogate branch executes before the later if (continueRemoval) guard and calls:

    directory.Delete();

    It then returns. Consequently, when ShouldProcess() returns false for -WhatIf, a junction or directory symbolic link is still detached.

    The reparse-point branch should also be gated by continueRemoval, or the method should return immediately when continueRemoval is false.

    A regression test should verify that:

    • directory symbolic links remain present after Remove-Item -WhatIf on supported platforms;
    • NTFS junctions remain present on Windows;
    • the behavior is also correct with the real-world -Recurse -Force -WhatIf combination.

    Since #19714 was labeled Issue-Bug and closed as a duplicate of this issue, could the same bug label also be applied to this primary tracking issue?

  15. Om-singhaI commented on Oct 16, 2026

    @Om-singhaI

    I would like to work on this one. The cause is the spot MatejKafka pointed to: in RemoveDirectoryInfoItem the branch that detaches symbolic links and junctions runs before the ShouldProcess answer is checked, so -WhatIf and a No to -Confirm still remove the link. I have a small fix that only takes that branch once ShouldProcess approves, plus Pester tests for a directory symbolic link and a junction, and I reproduced the bug and checked the fix on a local macOS build of master. @powershell/powershell could this be assigned to me?

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 providerIn-PRIndicates that a PR is out for the issueNeeds-TriageThe issue is new and needs to be triaged by a work group.WG-Cmdletsgeneral cmdlet issues

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions