# Checking Input: Validation Attributes

Validation attributes check a parameter's value before any line of the function runs: \[ValidateSet()\] allows only a list of choices and makes Tab fill them in, \[ValidateRange()\] keeps a number between two limits, \[ValidateNotNullOrEmpty()\] turns away an empty value, and Mandatory asks for one that's missing.

Journeyman · PowerShell · Updated November 10, 2026

## After this lesson you can

- Limit a parameter to a list of values with \[ValidateSet()\], and use the Tab completion it gives
- Check a parameter's value with \[ValidateRange()\], \[ValidateNotNullOrEmpty()\] and Mandatory before the function runs

## Key takeaways

- Validation attributes go on the lines above a parameter and check its value before any line of the function runs, so bad input never reaches your file.
- [ValidateSet('Chill', 'Upbeat', 'Focus')] allows only those values, and Tab and Ctrl+Space offer them as choices.
- [ValidateRange(1, 15)] keeps a number between two limits, both included.
- [ValidateNotNullOrEmpty()] turns away an empty value, such as a misspelled variable. [Parameter(Mandatory)] asks for a value that's missing.

Online forms check what you type before they let you press Send: an email needs an `@`, a birthday can't be in the future, and "state" is a list you pick from rather than a box you type in. They check at the door because bad data is far harder to fix once it's stored. Your playlist needs the same. If someone adds a song with the mood `Chil`, `Get-Song -Mood Chill` never finds it; if they type 45 minutes when they meant 4, every playlist built from the file comes out wrong. PowerShell's cmdlets check their input before they start, and your tools can too.

This lesson adds `Add-Song` to the playlist tools from *Advanced Functions: `[CmdletBinding()]`*. Add this function to `PlaylistTools.ps1`, below Get-Song, save, and load the file with `. .\PlaylistTools.ps1` in the practice folder:

```powershell
function Add-Song {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory)]
        [string]$Title,

        [ValidateNotNullOrEmpty()]
        [string]$Artist = 'Unknown',

        [Parameter(Mandatory)]
        [ValidateRange(1, 15)]
        [int]$Minutes,

        [Parameter(Mandatory)]
        [ValidateSet('Chill', 'Upbeat', 'Focus')]
        [string]$Mood,

        [string]$Path = 'road-trip.csv'
    )
    Add-Content -Path $Path -Value "$Title,$Artist,$Minutes,$Mood"
    Get-Song -Path $Path | Select-Object -Last 1
}
```

Add-Content adds the song as a new line at the end of the CSV file (*Writing to Files: `Set-Content`, `Add-Content` and `>`*), and the last line outputs the song it added, as an object. The lines in square brackets above each parameter are **validation attributes**: checks PowerShell makes on that parameter's value before the function's first line runs. Add a song that passes them all:

```powershell
Add-Song -Title 'Tunnel Echo' -Artist 'The Night Owls' -Minutes 4 -Mood Chill
```

```text
Title       Artist         Minutes Mood
-----       ------         ------- ----
Tunnel Echo The Night Owls 4       Chill
```

## A list of choices: \[ValidateSet()\]

`[ValidateSet('Chill', 'Upbeat', 'Focus')]` (read "validate set") allows only the values in its list, like a form's drop-down:

```powershell
Add-Song -Title 'Toll Booth Blues' -Minutes 4 -Mood Chil
```

```text
Add-Song: Cannot validate argument on parameter 'Mood'. The argument "Chil" does not belong to the set "Chill,Upbeat,Focus" specified by the ValidateSet attribute. Supply an argument that is in the set and then try the command again.
```

The message names the parameter, the value and every allowed choice, so the person can fix it at once. Capital letters don't matter to the check: `-Mood chill` passes, and goes into the file the way it was typed.

A set also tells PowerShell what to offer when you press Tab. Type `Add-Song -Title 'Toll Booth Blues' -Minutes 4 -Mood`, then a space, and press **Tab**:

```text
Add-Song -Title 'Toll Booth Blues' -Minutes 4 -Mood Chill
```

Press Tab again for `Focus`, and again for `Upbeat`, or **Ctrl+Space** to see all three at once (*Keyboard Shortcuts at the Prompt*). Tab writes each one with the set's own capital letters, so the file stays tidy.

## A range: \[ValidateRange()\]

`[ValidateRange(1, 15)]` keeps a number between two limits, and both limits are allowed. A song of 0 minutes is a typo, and so is one of 45:

```powershell
Add-Song -Title 'Toll Booth Blues' -Minutes 45 -Mood Upbeat
```

```text
Add-Song: Cannot validate argument on parameter 'Minutes'. The 45 argument is greater than the maximum allowed range of 15. Supply an argument that is less than or equal to 15 and then try the command again.
```

The `[int]` type turns away a word such as `four` first, as in *Parameters: `param()`*; the range then checks the number.

## Not empty, and not missing

`[Parameter(Mandatory)]` you've met: when a value is missing, PowerShell asks for it. It also turns away an empty one, so a song can't have the title `''`. `-Artist` isn't mandatory, because many songs in a playlist come from somewhere you don't know, so it has a default. But when someone does give an artist, it shouldn't be empty. That happens more than you'd think, from a misspelled variable:

```powershell
$band = 'Maple Street'
Add-Song -Title 'Toll Booth Blues' -Artist $bnad -Minutes 4 -Mood Upbeat
```

```text
Add-Song: Cannot validate argument on parameter 'Artist'. The argument is null or empty. Provide an argument that is not null or empty, and then try the command again.
```

`$bnad` was never set, so it holds nothing, which PowerShell calls *null*. `[ValidateNotNullOrEmpty()]` turns away both nothing and an empty `''`. Without it, the song would have gone into the file with no artist at all.

None of the three failures reached the file. Only Tunnel Echo was added:

```powershell
(Get-Song).Count
```

```text
8
```

Put the checks where a mistake costs something: a value that goes into a file, picks a folder, or decides what gets removed. Everything here works the same in Windows PowerShell 5.1 and on a Mac or Linux.

**Try it.** Give `Get-Song`'s `-Mood` the same `[ValidateSet()]`, load the file again, and type `Get-Song -Mood`, a space and Tab. What happens to `Get-Song -Mood Happy` now?

## Check yourself

2 questions to try on the lesson page.

## So what

A tool that checks its input at the door keeps your data clean and tells people exactly what it wanted, and Tab completion means they rarely get it wrong in the first place.

## Key terms

- [Validation Attribute](https://www.ask-codey.com/glossary/validation-attribute)
- [ValidateSet](https://www.ask-codey.com/glossary/validateset)
- [ValidateRange](https://www.ask-codey.com/glossary/validaterange)
- [Mandatory Parameter](https://www.ask-codey.com/glossary/mandatory-parameter)
- [Tab Completion](https://www.ask-codey.com/glossary/tab-completion-powershell)

## Cheat sheets

- [Checking Input: Validation Attributes](https://www.ask-codey.com/cheat-sheets/powershell-parameter-validation-cheat-sheet)

## Related

- [Advanced Functions: \`\[CmdletBinding()\]\`](https://www.ask-codey.com/lessons/powershell-advanced-functions)
- [Parameters: \`param()\`](https://www.ask-codey.com/lessons/powershell-param)
- [Taking Pipeline Input](https://www.ask-codey.com/lessons/powershell-pipeline-input)
- [Keyboard Shortcuts at the Prompt](https://www.ask-codey.com/lessons/powershell-keyboard-shortcuts)

Source: https://www.ask-codey.com/lessons/powershell-parameter-validation
