Skip to content

Commit ca810dd

Browse files
committed
checkpoint
1 parent 58af250 commit ca810dd

File tree

2 files changed

+61
-0
lines changed

2 files changed

+61
-0
lines changed

.squire/config.json

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
{
2+
"modules": {
3+
"./examples/layered_errors": {
4+
"name": "layered_errors",
5+
"role": [
6+
"lib"
7+
]
8+
},
9+
"./": {
10+
"name": "go-doterr",
11+
"role": [
12+
"lib"
13+
]
14+
},
15+
"./test": {
16+
"name": "test",
17+
"role": [
18+
"test"
19+
]
20+
},
21+
"./examples/basic_usage": {
22+
"name": "basic_usage",
23+
"role": [
24+
"lib"
25+
]
26+
},
27+
"./examples/combined_errors": {
28+
"name": "combined_errors",
29+
"role": [
30+
"lib"
31+
]
32+
}
33+
}
34+
}

README.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,33 @@ if errors.Is(err, ErrDriver) {
230230

231231
Why provide **two (2)** sentinels? It can often be useful to provide both a general purpose error — e.g. `ErrNotFound` — and a more-specific error — e.g. `ErrNoWidgetMatchedSearchTerm` — when characterizing errors.
232232

233+
## Parameter types for NewErr()
234+
235+
`NewErr(parts ...any)` accepts a variadic parameter, but **not all types are valid**:
236+
237+
| Valid | Type | Position | Example |
238+
|-------|------|----------|---------|
239+
|| Sentinel error | First 1-2 positions | `ErrRepo`, `ErrNotFound` |
240+
|| Metadata key (string) | Followed by value | `"table"` |
241+
|| Metadata value (any) | After key | `"users"`, `42`, `obj` |
242+
|| Cause error | Last position only | `err` |
243+
|| Descriptive string | Any | `"failed to connect"` |
244+
|| fmt.Sprintf result | Any | `fmt.Sprintf("error: %s", msg)` |
245+
246+
**Anti-pattern to avoid:**
247+
248+
```go
249+
// ❌ WRONG - descriptive strings are not sentinels
250+
return NewErr(ErrCmd, "failed to resolve config directory", err)
251+
return NewErr(ErrCmd, fmt.Sprintf("no branch found (tried: %s)", list))
252+
253+
// ✅ CORRECT - use sentinels + metadata
254+
return NewErr(ErrCmd, ErrResolvingConfigDir, err)
255+
return NewErr(ErrCmd, ErrNoBranchFound, "tried", list)
256+
```
257+
258+
Descriptive strings bypass `errors.Is()` and cannot be matched programmatically. If you need to describe a failure condition, create a sentinel error for it.
259+
233260
## Layered composition example
234261

235262
Each function layer defines **its own sentinel** and passes the error from the inner function as the trailing cause.

0 commit comments

Comments
 (0)