# Exercise: Make It Fail Well

Fix a photo mover that loses photos on a bad day, so a failed copy never deletes a photo, a photo with the same name is never replaced, its results stay apart from its messages and a summary prints whatever happens, then answer four questions on reading errors and debugging while a Pester check tries it for real.

Journeyman · PowerShell · Updated November 10, 2026

Every phone fills up eventually, and then the photos have to go somewhere: a laptop, a photo library, a USB drive. A script that moves them is a real time-saver, as long as it never loses one. This exercise's `move-photos.ps1` works on a good day. On a bad day, it loses photos without a word: when a copy fails, it deletes the photo anyway, and when the library already has a photo with the same name, it replaces it. Your job is to make it fail well, the way a script you'd hand to a friend or a coworker should. A Pester check runs your script on pretend photos and tells you which jobs are done.

## Get the exercise code

Open this lesson's GitHub repository, [github.com/ask-codey/exercise-powershell-make-it-fail-well](https://github.com/ask-codey/exercise-powershell-make-it-fail-well), also linked from the **Exercise** box beside the lesson. Click **Code**, then **Download ZIP**, and unzip it into your `terminal-practice` folder. Or clone it with Git.

The folder holds:

- `move-photos.ps1`: the photo mover, for you to finish.
- `phone\`: three pretend photos standing in for your phone, and `photo-library\`, which already has an older `IMG_0002.jpg` of its own.
- `reset-photos.ps1`: puts the pretend photos back the way they came, whenever you want to run the mover again.
- `answers.txt`: four questions, each with a numbered line for your answer.
- `Check.Tests.ps1`: the check. You don't need to change it.

## What to do

Open PowerShell in the exercise folder, the one with `answers.txt` in it, and open it in VS Code with `code .`. First, run the mover as it is, and look at the library's `IMG_0002.jpg`: the old photo is gone, replaced by the phone's. Phones start numbering again after a reset, so two different photos can share a name. Run `.\reset-photos.ps1` to get everything back. The script starts like this:

```powershell
foreach ($photo in Get-ChildItem $Source -File) {
    $to = "$Library\$($photo.Name)"
    Copy-Item -Path $photo.FullName -Destination $to
    Remove-Item -Path $photo.FullName
    Write-Host "Moved $($photo.Name)"
}
```

1. **A failed copy never loses a photo.** Use `try`, `catch` and `-ErrorAction Stop` so a failed copy never reaches `Remove-Item`. In `catch`, report it with `Write-Error`, naming the photo and saying it's still in the phone folder, then `exit 1`. Try it with a library that isn't there: `.\move-photos.ps1 -Library .\usb-library`.
2. **A photo already in the library is never replaced.** Check first with `Test-Path`. If the library has one with that name, leave the photo where it is, say so with `Write-Warning`, and go on to the next.
3. **Results go down the pipeline.** Output only the name of each photo that moved, with `Write-Output`, so `.\move-photos.ps1 | Measure-Object` counts them. Keep the heading on the screen with `Write-Host`.
4. **A summary, whatever happens.** Count the photos that move, and print `Photos moved: ` and the count with `Write-Host`, in a `finally` block, so it prints after a failed run too.

Then answer the four questions in `answers.txt`, using *Reading Errors, and `-ErrorAction`* and *Debugging in VS Code*.

## Check your work

The check uses Pester. If you haven't installed it yet, install it once:

```powershell
Install-PSResource Pester
```

Then, from the exercise folder:

```powershell
Invoke-Pester
```

At first most tests fail. That's expected: each job you finish turns its tests green. A failing test names the job and says what to look at, for example *Expected 1, because a run that failed should end with exit 1 in catch*. The check makes its own pretend photos in a throwaway folder and runs your script there, so it never touches `phone\` or `photo-library\`.

If PowerShell says the check can't be loaded because it is not digitally signed, Windows has marked the downloaded files as coming from the internet: from the exercise folder, run `Get-ChildItem -Recurse | Unblock-File` once, then `Invoke-Pester` again.

## Hints

- **`catch` sees only errors that stop.** Without `-ErrorAction Stop`, Copy-Item's error goes by in red and the script carries on to the delete (*`try`, `catch` and `finally`*).
- **`$photo` is still there in `catch`.** It holds the photo the loop was on, and `$Source` holds the phone folder's path, which is everything your message needs.
- **`continue` skips to the next photo.** You met it in *Stopping Early: `break` and `continue`*.
- **One `Write-Output` a photo.** A message such as "Moved IMG_0001.jpg" isn't a result: it would end up in a file or a count with the names (*Where Output Goes: `Write-Output`, `Write-Host` and Friends*).
- **Something you can't explain?** Put a breakpoint on the line, press F5, and step with F10, watching `$to` and `$moved`.

## When you're done

Every test is green, and Pester's last line says:

```text
Tests Passed: 13, Failed: 0, Skipped: 0, Inconclusive: 0, NotRun: 0
```

Run `.\reset-photos.ps1`, then the mover, and it says:

```text
Moving photos from .\phone to .\photo-library
IMG_0001.jpg
WARNING: IMG_0002.jpg is already in the library. Left it in .\phone.
IMG_0003.jpg
Photos moved: 2
```

Your warning's words can differ. Now run `.\reset-photos.ps1` and `.\move-photos.ps1 -Library .\usb-library`, and read your error message as if you'd never seen the script: does it tell you what happened, what's safe and what to do next?

## Submit your exercise

The exercise is how you finish this lesson. When your work is done, put it on GitHub in a repo of your own, then submit that repo's address here.

1. On GitHub, click **+**, then **New repository**. Name it (for example `exercise-powershell-make-it-fail-well`), choose **Public**, and click **Create repository**. Leave out the README: your folder already has one.
2. In a terminal in your exercise folder (PowerShell works), send your work to your new repo. If you downloaded the ZIP:

   ```powershell
   git init -b main
   git add .
   git commit -m "My solution"
   git remote add origin https://github.com/your-name/exercise-powershell-make-it-fail-well.git
   git push -u origin main
   ```

   If you cloned the starter instead, point your copy at your own repo, then commit and push:

   ```powershell
   git remote set-url origin https://github.com/your-name/exercise-powershell-make-it-fail-well.git
   git add .
   git commit -m "My solution"
   git push -u origin main
   ```

3. Paste your repo's address, such as `https://github.com/your-name/exercise-powershell-make-it-fail-well`, into **Submit your exercise** on this page. The site checks that the repo is public and holds your commits, and then the lesson is complete.

Changed something after you submitted? Push it, and submit again: your latest submission is the one that counts.

## So what

Any script can work on a good day. One that stops before it does harm, says what happened and keeps its results clean is one people can trust with their photos, their files and their servers.

## Key terms

- [try / catch](https://www.ask-codey.com/glossary/try-catch)
- [finally Block](https://www.ask-codey.com/glossary/finally-block-powershell)
- [ErrorAction](https://www.ask-codey.com/glossary/erroraction)
- [Write-Output](https://www.ask-codey.com/glossary/write-output)
- [Write-Host](https://www.ask-codey.com/glossary/write-host)
- [Breakpoint](https://www.ask-codey.com/glossary/breakpoint-powershell)

## Related

- [Reading Errors, and \`-ErrorAction\`](https://www.ask-codey.com/lessons/powershell-errors)
- [\`try\`, \`catch\` and \`finally\`](https://www.ask-codey.com/lessons/powershell-try-catch)
- [Where Output Goes: \`Write-Output\`, \`Write-Host\` and Friends](https://www.ask-codey.com/lessons/powershell-output-streams)
- [Debugging in VS Code](https://www.ask-codey.com/lessons/powershell-debugging-in-vs-code)

Source: https://www.ask-codey.com/lessons/exercise-powershell-make-it-fail-well
