How to Use PowerShell Remove-Item with Try Catch (With Real Examples)

When working with files and folders in PowerShell, the Remove-Item cmdlet is one of the most commonly used commands for deleting items. While it works well in straightforward scenarios, things don’t always go as planned. A file might be locked by another process, you may not have sufficient permissions, or the specified path may not exist. In such cases, your script can stop unexpectedly if errors aren’t handled properly.

This is where PowerShell’s Try...Catch statement becomes invaluable. By combining Remove-Item with Try...Catch, you can gracefully handle errors, display meaningful messages, log failures, or continue executing the rest of your script without interruption.

In this tutorial, you’ll learn how to use Remove-Item with Try Catch properly in PowerShell with some real examples.

Let’s get into it.

What Is Remove-Item in PowerShell?

Remove-Item is the PowerShell cmdlet you use to delete files, folders, registry keys, and more. It’s the PowerShell equivalent of hitting the Delete key — or more accurately, Shift + Delete, because there’s no Recycle Bin involved.

Basic syntax looks like this:

Remove-Item -Path "C:\Temp\oldfile.txt"

It’s simple and works well in most cases. But the moment something goes wrong — the file doesn’t exist, it’s locked by another process, or you don’t have permission — that’s when things get messy.

Check out PowerShell Script to Delete Files Older Than 30 Days

Why You Need Try Catch with Remove-Item

Here’s the thing most beginners miss: Remove-Item does not throw a terminating error by default.

Let me explain what that means in plain English.

In PowerShell, errors come in two types:

  • Terminating errors — These stop the script cold and can be caught with Try Catch.
  • Non-terminating errors — These are logged, a message is shown, but the script keeps running. Try Catch completely ignores them.

By default, Remove-Item throws a non-terminating error. So if you wrap it in a Try Catch block without any changes, the Catch block will never run. This trips up a lot of people, and it’s the number one reason I see broken error handling in PowerShell scripts.

Here’s the fix: you need to add -ErrorAction Stop to Remove-Item. This tells PowerShell to treat any error from that command as a terminating error — which means Try Catch can actually catch it.

The Basic Try Catch Structure in PowerShell

Before jumping into Remove-Item specifically, let’s quickly look at how Try Catch works in PowerShell.

try {
# Code that might fail
}
catch {
# What to do if it fails
}
finally {
# Optional: This always runs, whether or not there was an error
}
  • The try block runs your code.
  • If something goes wrong (and it’s a terminating error), execution jumps to the catch block.
  • The finally block runs no matter what — error or not.

Inside the catch block, you can access error details using $_. For example, $_.Exception.Message gives you the human-readable error message.

Check out How To Delete File If Exists In PowerShell?

Method 1: Basic Remove-Item with Try Catch

This is your starting point. Always use -ErrorAction Stop so the Catch block actually fires.

try {
Remove-Item -Path "C:\Users\fewli\Downloads\Test.txt" -ErrorAction Stop
Write-Host "File deleted successfully."
}
catch {
Write-Host "Failed to delete the file. Error: $($_.Exception.Message)"
}

If the file exists and you have permission, you’ll see:

File deleted successfully.

You can see the exact output in the screenshot below:

PowerShell Remove-Item with Try Catch

If the file doesn’t exist or there’s a permissions issue, you’ll see something like:

Failed to delete the file. Error: Cannot find path 'C:\Temp\oldfile.txt' because it does not exist.

Clean, clear, and useful. This alone is miles better than letting your script crash without context.

Check out How to Delete a File in PowerShell?

Method 2: Check if the File Exists First with Test-Path

Sometimes the simplest approach is the best one. Before trying to delete a file, just check if it exists using Test-Path. If it doesn’t exist, don’t even try to delete it.

$filePath = "C:\Temp\oldfile.txt"

if (Test-Path $filePath) {
try {
Remove-Item -Path $filePath -ErrorAction Stop
Write-Host "Deleted: $filePath"
}
catch {
Write-Host "Error deleting $filePath : $($_.Exception.Message)"
}
}
else {
Write-Host "File not found: $filePath"
}

This is great for situations where the file may or may not exist, and both outcomes are valid. You’re not treating a missing file as an error — you’re just handling it differently.

One thing to keep in mind: there’s a tiny race condition possible here. Technically, a file could be deleted between when Test-Path checks and when Remove-Item runs.

In most real-world scripts this isn’t a concern, but it’s good to know. That’s why combining Test-Path with Try Catch (like the example above) is the safest approach.

Method 3: Deleting Multiple Files with a Loop

What if you need to delete a whole list of files? Maybe you have a text file with paths, or you’re cleaning up a folder. The trick here is to loop through each file individually and handle errors per file — not all at once.

Here’s an example where you’re reading file paths from a text file and deleting each one:

$fileList = Get-Content "C:\Cleanup\files_to_delete.txt"

foreach ($file in $fileList) {
try {
Remove-Item -Path $file -ErrorAction Stop
Write-Host "Deleted: $file"
}
catch {
Write-Host "Could not delete '$file': $($_.Exception.Message)"
}
}

Each file gets its own Try Catch, so if one fails (maybe it’s locked or missing), the loop continues to the next one. You don’t lose the whole batch just because one file had an issue.

You can also log the results to a file by piping the output:

$fileList = Get-Content "C:\Cleanup\files_to_delete.txt"
$logPath = "C:\Cleanup\deletion_log.txt"

foreach ($file in $fileList) {
try {
Remove-Item -Path $file -ErrorAction Stop
"Deleted: $file" | Out-File -Append $logPath
}
catch {
"Failed: $file — $($_.Exception.Message)" | Out-File -Append $logPath
}
}

Now you’ve got a clean log showing exactly what happened to each file. Super useful when you’re running cleanup scripts on servers and need to audit the results later.

Method 4: Deleting a Folder (Including Everything Inside It)

Deleting a folder and all its contents is a common task. You use -Recurse to remove everything inside, and -Force to suppress prompts and push through read-only files.

$folderPath = "C:\Temp\OldBackups"

try {
Remove-Item -Path $folderPath -Recurse -Force -ErrorAction Stop
Write-Host "Folder deleted: $folderPath"
}
catch {
Write-Host "Failed to delete folder: $($_.Exception.Message)"
}

A few things to watch out for here:

  • If any file in the folder is open or locked by another process, Remove-Item will fail.
  • -Force removes read-only files, but it won’t force-close file locks held by running processes.
  • If you’re deleting a folder with many nested files and one fails, the whole operation errors out.

If you need granular control over which files get deleted inside a folder, loop through them individually with Get-ChildItem (more on this below).

Method 5: Deleting Files in a Folder One by One

When you use Remove-Item -Recurse and one file fails, the whole command can error out. If you want to delete files one by one and handle each failure separately, combine Get-ChildItem with a foreach loop:

$folderPath = "C:\Temp\OldLogs"

Get-ChildItem -Path $folderPath -File | ForEach-Object {
try {
Remove-Item -Path $_.FullName -ErrorAction Stop
Write-Host "Deleted: $($_.FullName)"
}
catch {
Write-Host "Could not delete $($_.Name): $($_.Exception.Message)"
}
}

This gives you full control. If a file is locked, you know exactly which one it is and your script continues deleting the rest. Much better than watching a recursive delete fail halfway through and not knowing what happened.

Method 6: Catching Specific Exception Types

Sometimes you want to handle different errors differently. For example, maybe a “file not found” error should just be logged quietly, but an “access denied” error should send an alert or stop the script entirely.

You can catch specific exception types in PowerShell like this:

$filePath = "C:\Temp\report.txt"

try {
Remove-Item -Path $filePath -ErrorAction Stop
Write-Host "File deleted."
}
catch [System.UnauthorizedAccessException] {
Write-Warning "Access denied. You don't have permission to delete this file."
}
catch [System.IO.FileNotFoundException] {
Write-Warning "File not found — maybe it was already deleted."
}
catch {
Write-Host "Unexpected error: $($_.Exception.Message)"
}

The last catch block (without a specific exception type) acts as a catch-all. Any error that doesn’t match the specific types above will land here.

To find out what exception type an error is, you can run this after an error occurs:

$Error[0].Exception.GetType().FullName

That’ll give you the full name of the exception, which you can then use in your specific catch blocks.

Method 7: Using the Finally Block for Cleanup

The finally block runs after the try and catch, no matter what happened. This is useful when you need to clean something up after an operation — like closing a log file, releasing a lock, or resetting a variable.

Here’s a practical example:

$tempFile = "C:\Temp\process_output.txt"

try {
# Do some work that creates a temp file
"Processing done." | Out-File $tempFile
# Simulate an error
Remove-Item -Path "C:\Temp\nonexistent.txt" -ErrorAction Stop
}
catch {
Write-Host "Error occurred: $($_.Exception.Message)"
}
finally {
if (Test-Path $tempFile) {
Remove-Item -Path $tempFile -ErrorAction SilentlyContinue
Write-Host "Temporary file cleaned up."
}
}

Notice I used -ErrorAction SilentlyContinue inside the finally block. Since I’m already in cleanup mode, I don’t want the finally block itself to throw an error. If the temp file doesn’t exist, I just want to move on silently.

Using $ErrorActionPreference for Global Settings

If you’re writing a longer script and want every command to behave like it has -ErrorAction Stop, you can set this at the top:

$ErrorActionPreference = "Stop"

After this line, any error in your script will be treated as terminating, so your Try Catch blocks will work everywhere without adding -ErrorAction Stop to every single line.

Just be careful — this also applies to commands you might want to silently fail. If a command fails and there’s no Try Catch around it, your script will stop. Use this when you want strict error handling throughout and plan your error handling accordingly.

Using -ErrorVariable to Capture Errors

Another useful trick: the -ErrorVariable parameter. It lets you capture error information into a named variable instead of relying on $_ inside catch.

Remove-Item -Path "C:\Temp\file.txt" -ErrorAction SilentlyContinue -ErrorVariable deleteError

if ($deleteError) {
Write-Host "Error: $($deleteError[0].Exception.Message)"
}

This approach is handy when you don’t want to use Try Catch but still want to check what went wrong after the fact. It’s also useful inside loops where you want to inspect errors after the loop finishes.

Common Mistakes to Avoid

Here are the mistakes I see most often when people use Remove-Item with error handling:

  • Forgetting -ErrorAction Stop — Without it, Catch never runs. This is the single most common issue.
  • Using one Remove-Item for many files without a loop — If you pass multiple paths and one fails, you lose granular error info.
  • Not checking file existence before deleting — Combine Test-Path with Try Catch for the most robust approach.
  • Catching errors but doing nothing — An empty catch block is almost as bad as no error handling. At minimum, log the error.
  • Using -Force without understanding what it does — -Force bypasses read-only attributes but does not unlock files held open by processes.

Quick Reference

Here’s a summary of the key pieces you’ll use most:

  • Remove-Item -Path "path" -ErrorAction Stop — Makes the error catchable
  • try { } catch { } — Wrap your delete operation
  • $_.Exception.Message — Get the error message inside catch
  • Test-Path — Check if a file exists before deleting
  • -Recurse -Force — Delete folders and their contents
  • $ErrorActionPreference = "Stop" — Make all errors terminating globally
  • -ErrorVariable myVar — Capture errors into a named variable
  • finally { } — Run cleanup code no matter what

A Real-World Script Putting It All Together

Here’s a complete script that reads a list of files to delete from a text file, deletes each one with proper error handling, and writes a log:

$ErrorActionPreference = "Stop"

$inputFile = "C:\Cleanup\files_to_remove.txt"
$logFile = "C:\Cleanup\deletion_log_$(Get-Date -Format 'yyyyMMdd_HHmmss').txt"

if (-not (Test-Path $inputFile)) {
Write-Host "Input file not found: $inputFile"
exit
}

$files = Get-Content $inputFile

foreach ($file in $files) {
if (Test-Path $file) {
try {
Remove-Item -Path $file -Force -ErrorAction Stop
$msg = "[SUCCESS] Deleted: $file"
}
catch {
$msg = "[FAILED] Could not delete '$file': $($_.Exception.Message)"
}
}
else {
$msg = "[SKIPPED] File not found: $file"
}

Write-Host $msg
$msg | Out-File -Append $logFile
}

Write-Host "`nLog saved to: $logFile"

This script is safe, clear, and logs everything. You can run it on a schedule, hand it to a colleague, or drop it into a maintenance routine with confidence.

Wrapping Up

Error handling in PowerShell isn’t complicated once you understand the terminating vs non-terminating error distinction. The key takeaway is simple: always add -ErrorAction Stop when using Remove-Item inside a Try Catch block, otherwise your error handling won’t work at all.

From there, it’s about choosing the right pattern for your situation — a basic try/catch for single files, a loop for multiple files, specific exception catches for different failure types, and a finally block when you need guaranteed cleanup.

You may also like:

100 PowerShell cmdlets download free

100 POWERSHELL CMDLETS E-BOOK

FREE Download an eBook that contains 100 PowerShell cmdlets with complete script and examples.