mcpbeat Sign in

Go Error Handling Agent Skill

by cxuu

Use when writing Go code that returns, wraps, or handles errors — choosing between sentinel errors, custom types, and fmt.Errorf (%w vs %v), structuring error flow, or deciding whether to log or return. Also use when propagating errors across package boundaries or using errors.Is/As, even if the user doesn't ask about error strategy. Does not cover panic/recover patterns (see go-defensive).

7k tokens
context cost
the whole folder, loaded on every use
6
files
ships runnable scripts
0
copies elsewhere
how many repositories repackaged it
136
stars on the repo
on the repository, not the skill itself

Install

one command, takes just this skill from the repository
npx skills add https://github.com/cxuu/golang-skills --skill go-error-handling

The instruction itself

13 sections, as written by the author

Go Error Handling

> Compatibility: errors.Is, errors.As, and %w wrapping require Go 1.13+; structured logging examples may use log/slog from Go 1.21+.

Resource Routing

  • scripts/check-errors.sh - Run when checking string-based error matching, bare error propagation, and log-and-return patterns.
  • scripts/check-errors-ast.go - Implementation helper invoked by check-errors.sh; patch this when changing error-flow analysis behavior.
  • references/ERROR-FLOW.md - Read when deciding where to handle, wrap, log, or return errors.
  • references/ERROR-TYPES.md - Read when choosing sentinel errors, typed errors, or opaque errors.
  • references/WRAPPING.md - Read when choosing %w versus %v or crossing package boundaries.

In Go, errors are values — they are

created by code and consumed by code.

Choosing an Error Strategy

  • System boundary (RPC, IPC, storage)? → Wrap with %v to avoid leaking internals
  • Caller needs to match specific conditions? → Sentinel or typed error, wrap with %w
  • Caller just needs debugging context? → fmt.Errorf("...: %w", err)
  • Leaf function, no wrapping needed? → Return the error directly

Default: wrap with %w and place it at the end of the format string.


Core Rules

Never Return Concrete Error Types

Never return concrete error types from exported functions — a concrete nil

pointer can become a non-nil interface:

// Bad: Concrete type can cause subtle bugs
func Bad() *os.PathError { /*...*/ }

// Good: Always return the error interface
func Good() error { /*...*/ }

Error Strings

Error strings should not be capitalized and should not end with

punctuation. Exception: exported names, proper nouns, or acronyms.

// Bad
err := fmt.Errorf("Something bad happened.")

// Good
err := fmt.Errorf("something bad happened")

For displayed messages (logs, test failures, API responses), capitalization is

appropriate.

Return Values on Error

When a function returns an error, callers must treat all non-error return values

as unspecified unless explicitly documented.

Tip: Functions taking a context.Context should usually return an error

so callers can determine if the context was cancelled.


Handling Errors

When encountering an error, make a deliberate choice — do not discard

with _:

  • Handle immediately — address the error and continue
  • Return to caller — optionally wrapped with context
  • In exceptional cases — log.Fatal or panic

To intentionally ignore: add a comment explaining why.

n, _ := b.Write(p) // never returns a non-nil error

For related concurrent operations, use

errgroup:

g, ctx := errgroup.WithContext(ctx)
g.Go(func() error { return task1(ctx) })
g.Go(func() error { return task2(ctx) })
if err := g.Wait(); err != nil { return err }

Avoid In-Band Errors

Don't return -1, nil, or empty string to signal errors. Use multiple

returns:

// Bad: In-band error value
func Lookup(key string) int  // returns -1 for missing

// Good: Explicit error or ok value
func Lookup(key string) (string, bool)

This prevents callers from writing Parse(Lookup(key)) — it causes a

compile-time error since Lookup(key) has 2 outputs.


Error Flow

Handle errors before normal code. Early returns keep the happy path unindented:

// Good: Error first, normal code unindented
if err != nil {
    return err
}
// normal code

Handle errors once — either log or return, never both:

Error encountered?
├─ Caller can act on it? → Return (with context via %w)
├─ Top of call chain? → Log and handle
└─ Neither? → Log at appropriate level, continue

Error Types

> Advisory: Recommended best practice.

| Caller needs to match? | Message type | Use |

|------------------------|--------------|-----|

| No | static | errors.New("message") |

| No | dynamic | fmt.Errorf("msg: %v", val) |

| Yes | static | var ErrFoo = errors.New("...") |

| Yes | dynamic | custom error type |

Default: Wrap with fmt.Errorf("...: %w", err). Escalate to sentinels for

errors.Is(), to custom types for errors.As().


Error Wrapping

> Advisory: Recommended best practice.

  • Use %v: At system boundaries, for logging, to hide internal details
  • Use %w: To preserve error chain for errors.Is/errors.As

Key rules: Place %w at the end. Add context callers don't have. If

annotation adds nothing, return err directly.

> Validation: After implementing error handling, run bash scripts/check-errors.sh to detect common anti-patterns. Then run go vet ./... to catch additional issues.


  • Error naming: See go-naming when naming sentinel errors (ErrFoo) or custom error types
  • Testing errors: See go-testing when testing error semantics with errors.Is/errors.As or writing error-checking helpers
  • Panic handling: See go-defensive when deciding between panic and error returns, or writing recover guards
  • Guard clauses: See go-control-flow when structuring early-return error flow or reducing nesting
  • Logging decisions: See go-logging when choosing log levels, configuring structured logging, or deciding what context to include in log messages

Other skills for the same job

different authors, same section of the catalogue
Changelog Generator
by frostant
×9

Automatically creates user-facing changelogs from git commits by analyzing commit history, categorizing changes, and transforming technical commits into clear, customer-friendly release notes. Turns hours of manual changelog writing into minutes of automated generation.

774 tokens
Codex
by softaworks
×2

Use when the user asks to run Codex CLI (codex exec, codex resume) or references OpenAI Codex for code analysis, refactoring, or automated editing. Uses GPT-5.2 by default for state-of-the-art software engineering.

2k tokens
Memory Safety Patterns
by ComeOnOliver
×2

Implement memory-safe programming with RAII, ownership, smart pointers, and resource management across Rust, C++, and C. Use when writing safe systems code, managing resources, or preventing memory bugs.

6k tokens
Pysam
by K-Dense-AI
×1

Python/HTSlib workflows for genomic files. Use when reading, querying, filtering, or writing SAM/BAM/CRAM, VCF/BCF, FASTA/FASTQ, or tabix data with pysam, including pileup, coverage, indexing, and CRAM references.

34k tokens scripts
Scientific Critical Thinking
by K-Dense-AI
×1

Evaluate scientific claims and evidence quality. Use for assessing experimental design validity, identifying biases and confounders, applying evidence grading frameworks (GRADE, Cochrane Risk of Bias), or teaching critical analysis. Best for understanding evidence quality, identifying flaws. For formal peer review writing use peer-review.

26k tokens
Gh Fix CI
by openai
vendor ×1

Use when a user asks to debug or fix failing GitHub PR checks that run in GitHub Actions; use `gh` to inspect checks and logs, summarize failure context, draft a fix plan, and implement only after explicit approval. Treat external providers (for example Buildkite) as out of scope and report only the details URL.

8k tokens scripts
Declarative Agent Developer
by microsoft
vendor ×1

> Create, build, deploy, and localize declarative agents for M365 Copilot and Teams. USE THIS SKILL for ANY task involving a declarative agent — including localization, scaffolding, editing manifests, adding capabilities, and deploying. Localization requires tokenized manifests and language files that only this skill knows how to produce. "scaffold an agent", "new agent project", "add a capability", "add a plugin", "configure my agent", "deploy my agent", "fix my agent manifest", "edit my agent", "localize my agent", "add localization", "translate my agent", "multi-language agent", "add an API plugin", "add an MCP plugin", "add OAuth to my plugin", "review instructions", "improve instructions", "fix my instructions"

66k tokens
Documentation
by lingxling
×1

Documentation generation workflow covering API docs, architecture docs, README files, code comments, and technical writing.

1k tokens

How to use it

Copy the folder

Take cxuu/go-error-handling from the repository into ~/.claude/skills for personal use, or into .claude/skills inside a project.

Check the name does not clash

The agent identifies a skill by the name field in its header. Two skills with the same name cannot sit side by side — one of them will be ignored.