# Go Sentinel Errors

> Define package-level sentinel errors using errors.New Use when this capability is needed.

- Skill: `tomevault-io/go-sentinel-errors` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add tomevault-io/go-sentinel-errors`
- Raw SKILL.md: https://api.skillmd.com/api/skills/tomevault-io/go-sentinel-errors/raw
- Safety review: pending (external: skill-scanner PASS, skillspector PASS)
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: tomevault-io (https://skillmd.com/u/tomevault-io)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/tomevault-io/go-sentinel-errors

---


# Sentinel Errors

## Pattern
Define package-level errors as exported variables for expected error conditions.

## CORRECT
```go
package user

import "errors"

// Sentinel errors - define at package level
var (
    ErrNotFound      = errors.New("user not found")
    ErrInvalidEmail  = errors.New("invalid email format")
    ErrDuplicate     = errors.New("user already exists")
)

func Get(id int) (*User, error) {
    u, ok := db[id]
    if !ok {
        return nil, ErrNotFound
    }
    return u, nil
}
```

## WRONG
```go
// Bad: Creates new error each time (can't use errors.Is)
func Get(id int) (*User, error) {
    if _, ok := db[id]; !ok {
        return nil, errors.New("user not found")
    }
    return db[id], nil
}

// Bad: String comparison is fragile
if err.Error() == "user not found" { }
```

## Naming Convention
- Prefix with `Err`
- Use camel case: `ErrNotFound`, not `ERR_NOT_FOUND`
- Be specific: `ErrInvalidEmail`, not `ErrBadInput`

## When to Use
Use sentinel errors for:
- Expected business logic errors
- Public API boundaries
- Conditions callers need to handle differently

Avoid for:
- Unexpected/rare conditions
- Internal implementation details

---
> Converted and distributed by [TomeVault](https://tomevault.io/claim/jamesprial) — claim your Tome and manage your conversions.
<!-- tomevault:4.0:skill_md:2026-04-13 -->

