Go error handling patterns including wrapping, custom error types, errors.Is/As, and error conventions. Use when handling, creating, or checking errors in Go.
Provides expert guidance for Go error handling patterns including wrapping with %w, custom error types, errors.Is/As, and sentinel errors. Use when creating, handling, or checking errors in Go code to ensure proper error propagation and inspection.
/plugin marketplace add jovermier/cc-stack-marketplace/plugin install cc-go@cc-stack-marketplaceThis skill inherits all available tools. When active, it can use any tool Claude has access to.
references/custom-errors.mdreferences/inspection.mdreferences/sentinel.mdreferences/wrapping.mdExpert guidance for proper error handling in Go.
| Operation | Pattern | Example |
|---|---|---|
| Wrap with context | fmt.Errorf with %w | fmt.Errorf("opening file: %w", err) |
| Create custom error | struct with Error() | type ValidationError struct {...} |
| Check error type | errors.Is | errors.Is(err, ErrNotFound) |
| Extract error | errors.As | errors.As(err, &validationErr) |
| Sentinel errors | var at package level | var ErrNotFound = errors.New("not found") |
| Ignore errors | Never | Always check err != nil |
Specify a number or describe your error handling scenario.
| Response | Reference to Read |
|---|---|
| 1, "wrap", "context", "fmt.Errorf" | wrapping.md |
| 2, "custom", "type", "struct" | custom-errors.md |
| 3, "check", "errors.Is", "errors.As" | inspection.md |
| 4, "sentinel", "package", "global" | sentinel.md |
| 5, general error handling | Read relevant references |
// Good: Wrap with context using %w
func (s *Service) Process(id string) error {
item, err := s.repo.Find(id)
if err != nil {
return fmt.Errorf("finding item %s: %w", id, err)
}
// ...
}
// Bad: Wrapping with %v loses error type
return fmt.Errorf("finding item %s: %v", id, err) // Can't use errors.Is()
// Bad: Double wrapping
return fmt.Errorf("processing: %w", fmt.Errorf("finding: %w", err))
// Define custom error type
type ValidationError struct {
Field string
Message string
}
func (e *ValidationError) Error() string {
return fmt.Sprintf("validation failed for field %s: %s", e.Field, e.Message)
}
// Return custom error
func (s *Service) Validate(input Input) error {
if input.Email == "" {
return &ValidationError{
Field: "email",
Message: "is required",
}
}
return nil
}
// Check for sentinel error
if errors.Is(err, ErrNotFound) {
// Handle not found
}
// Extract and check custom error type
var validationErr *ValidationError
if errors.As(err, &validationErr) {
// Access validationErr.Field, validationErr.Message
}
// Check multiple possibilities
if errors.Is(err, ErrNotFound) || errors.Is(err, ErrAccessDenied) {
// Handle both cases
}
// Package-level sentinel errors
var (
ErrNotFound = errors.New("not found")
ErrAccessDenied = errors.New("access denied")
ErrInvalidInput = errors.New("invalid input")
)
// Use in returns
func (r *Repository) Find(id string) (*Item, error) {
// ...
return nil, ErrNotFound
}
// Check in callers
if err != nil {
if errors.Is(err, ErrNotFound) {
return nil, nil // Not found is not an error here
}
return nil, err // Other errors are still errors
}
| Scenario | Action |
|---|---|
| Crossing package boundary | Wrap with context |
| Internal function | Return as-is |
| Adding retry logic | Don't wrap (check with errors.Is) |
| Adding logging | Log then wrap or return |
| API layer | Wrap for user-friendly messages |
| Mistake | Severity | Fix |
|---|---|---|
| Ignoring errors | Critical | Always check err != nil |
| Using %v instead of %w | High | Use %w to preserve error type |
| Double wrapping | Medium | Wrap only at boundary |
| Panicking on errors | Critical | Return errors, don't panic |
| Creating strings for errors | Low | Use errors.New() or sentinel |
| Wrapping nil error | Medium | Check err != nil before wrapping |
| File | Topics |
|---|---|
| wrapping.md | fmt.Errorf with %w, when to wrap |
| custom-errors.md | Error types, methods, best practices |
| inspection.md | errors.Is, errors.As, type switches |
| sentinel.md | Package-level errors, comparison |
Error handling is correct when:
This skill should be used when the user asks to "create a slash command", "add a command", "write a custom command", "define command arguments", "use command frontmatter", "organize commands", "create command with file references", "interactive command", "use AskUserQuestion in command", or needs guidance on slash command structure, YAML frontmatter fields, dynamic arguments, bash execution in commands, user interaction patterns, or command development best practices for Claude Code.
This skill should be used when the user asks to "create an agent", "add an agent", "write a subagent", "agent frontmatter", "when to use description", "agent examples", "agent tools", "agent colors", "autonomous agent", or needs guidance on agent structure, system prompts, triggering conditions, or agent development best practices for Claude Code plugins.
This skill should be used when the user asks to "create a hook", "add a PreToolUse/PostToolUse/Stop hook", "validate tool use", "implement prompt-based hooks", "use ${CLAUDE_PLUGIN_ROOT}", "set up event-driven automation", "block dangerous commands", or mentions hook events (PreToolUse, PostToolUse, Stop, SubagentStop, SessionStart, SessionEnd, UserPromptSubmit, PreCompact, Notification). Provides comprehensive guidance for creating and implementing Claude Code plugin hooks with focus on advanced prompt-based hooks API.