About
This skill diagnoses runtime issues in Go programs, including panics, deadlocks, goroutine/memory leaks, and OOM kills. It helps developers interpret stack traces, race reports, and use tools like delve and pprof. Use it for debugging active failures, but not for performance optimization, writing new concurrent code, or test design.
Quick Install
Claude Code
Recommendednpx skills add eduardo-sl/go-agent-skills -a claude-code/plugin add https://github.com/eduardo-sl/go-agent-skillsgit clone https://github.com/eduardo-sl/go-agent-skills.git ~/.claude/skills/go-troubleshootingCopy and paste this command in Claude Code to install this skill
Documentation
Go Troubleshooting
Diagnosis before fixes. Reproduce, observe, localize, then change code. Never "fix" a symptom you haven't explained — the bug will move.
1. Pick the Procedure by Symptom
| Symptom | Procedure |
|---|---|
| Crash with stack trace | §2 Read the panic |
| Program hangs / requests stall | §3 Dump goroutines, find the block |
fatal error: all goroutines are asleep | §3 — Go detected total deadlock |
| Memory grows until OOM | §4 Heap profile diff |
| Goroutine count grows | §5 Goroutine profile diff |
| Intermittent corrupt data / weird values | §6 Race detector |
| Need to inspect state interactively | §7 Delve |
2. Reading a Panic
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x6bb0e4]
goroutine 43 [running]:
myapp/internal/service.(*UserService).Notify(0x0, {0xc000123456?, ...})
/app/internal/service/user.go:87 +0x24
myapp/internal/handler.(*Handler).Create(0xc0001a2000, ...)
/app/internal/handler/user.go:41 +0x1c5
Read it mechanically:
- First line: what kind of panic.
nil pointer dereference+addr=0x0means a nil receiver, nil field, or nil map/pointer argument. - Top frame in YOUR code:
user.go:87— go there. - Receiver value in the frame:
(*UserService).Notify(0x0, ...)— the0x0first argument IS the receiver: the service itself was nil. Trace where it was constructed (or wasn't). goroutine 43— if it's not goroutine 1, find who spawned it and whether a recover boundary should exist there.
3. Hangs and Deadlocks
Get a goroutine dump from the hanging process:
kill -QUIT <pid> # dumps all goroutine stacks to stderr, then exits
# or, if net/http/pprof is mounted (see §4):
curl 'localhost:6060/debug/pprof/goroutine?debug=2'
Then classify the stacks:
[semacquire]onsync.(*Mutex).Lock— find which goroutine HOLDS the mutex: look for another stack inside the critical section. Two goroutines each holding one of two locks = lock-order inversion.[chan send]/[chan receive]— the other side is gone. Find who should be receiving/sending and why it exited (or was never started).[select]with actx.Done()case missing — blocked call that ignores cancellation.- Hundreds of identical stacks — that's a leak (§5), not a deadlock.
4. Memory Leaks
Mount pprof in long-running services (private port only, never public):
import _ "net/http/pprof"
go func() {
log.Println(http.ListenAndServe("localhost:6060", nil))
}()
Diff heap profiles over time — a leak is growth that never returns:
curl -s localhost:6060/debug/pprof/heap > heap1.pb.gz
sleep 300 # let the leak accumulate
curl -s localhost:6060/debug/pprof/heap > heap2.pb.gz
go tool pprof -base heap1.pb.gz heap2.pb.gz
(pprof) top # biggest positive delta = the leak
(pprof) list FuncName
Usual suspects: unbounded caches/maps without eviction, subslices
pinning large arrays, time.Ticker never stopped, response bodies not
closed, growing global slices, forgotten goroutines holding buffers.
5. Goroutine Leaks
curl -s localhost:6060/debug/pprof/goroutine > g1.pb.gz
sleep 300
curl -s localhost:6060/debug/pprof/goroutine > g2.pb.gz
go tool pprof -base g1.pb.gz g2.pb.gz
(pprof) top # the growing stack is your leak site
The leaking stack tells you which go statement never terminates.
Fix the termination path (context, channel close) — patterns in the
concurrency skill. In tests, goleak (uber-go/goleak) fails a test
that leaves goroutines behind.
6. Race Detector
go test -race ./... # in CI, always
go build -race ./cmd/api # staging binaries under real traffic
A report shows two stacks: the write and the concurrent read/write,
each with the goroutine's creation site. The fix is never "add a
sleep" — protect the state (mutex), transfer ownership (channel), or
make it immutable. -race only reports races that actually executed:
a clean run proves nothing about untested paths.
7. Delve
dlv test ./internal/service -- -test.run TestTransfer # debug a test
dlv attach <pid> # running process
dlv core ./api core.1234 # post-mortem
(dlv) break user.go:87
(dlv) continue
(dlv) print svc.repo # inspect exact values
(dlv) goroutines -t # all goroutines with stacks
(dlv) goroutine 43 bt # switch and backtrace
Use delve when you need actual values or goroutine states, not just
locations. For quick localizations, a focused t.Logf or slog.Debug
plus one test run is often faster.
8. Diagnostic Environment Variables
GOTRACEBACK=all ./api # panic dumps ALL goroutines, not just one
GODEBUG=gctrace=1 ./api # GC cycles: pacing, heap goal, pause times
GOMEMLIMIT=512MiB ./api # soft memory limit — mitigates OOM while
# you find the real leak
Verification Checklist
- Symptom reproduced (or captured via dump/profile) before any code change
- Root cause explained: you can say WHY the failure happened at that site
- Panic fixes address the nil/bounds source, not a wrapper
recover - Deadlock fixes establish a single lock order or remove the shared lock
- Leak fixes verified: goroutine/heap profile flat after the fix
go test -race ./...passes after concurrency-related fixes- A regression test now fails without the fix
- pprof endpoints bound to localhost/private interfaces only
GitHub Repository
Frequently asked questions
What is the go-troubleshooting skill?
go-troubleshooting is a Claude Skill by eduardo-sl. Skills package instructions and resources that Claude loads on demand, so Claude can perform go-troubleshooting-related tasks without extra prompting.
How do I install go-troubleshooting?
Use the install commands on this page: add go-troubleshooting to Claude Code as a plugin, or clone its repository into your skills directory, then restart Claude so it picks up the skill.
What category does go-troubleshooting belong to?
go-troubleshooting is in the Testing category, tagged ai, testing, and design.
Is go-troubleshooting free to use?
Yes. go-troubleshooting is listed on AIMCP and free to install.
Related Skills
This Claude Skill runs the lm-evaluation-harness to benchmark LLMs across 60+ standardized academic tasks like MMLU and GSM8K. It's designed for developers to compare model quality, track training progress, or report academic results. The tool supports various backends including HuggingFace and vLLM models.
This skill provides comprehensive knowledge for implementing Cloudflare Cron Triggers to schedule Workers using cron expressions. It covers setting up periodic tasks, maintenance jobs, and automated workflows while handling common issues like invalid cron expressions and timezone problems. Developers can use it for configuring scheduled handlers, testing cron triggers, and integrating with Workflows and Green Compute.
This Claude Skill provides a Playwright-based toolkit for testing local web applications through Python scripts. It enables frontend verification, UI debugging, screenshot capture, and log viewing while managing server lifecycles. Use it for browser automation tasks but run scripts directly rather than reading their source code to avoid context pollution.
This skill helps developers complete finished work by verifying tests pass and then presenting structured integration options. It guides the workflow for merging, creating PRs, or cleaning up branches after implementation is done. Use it when your code is ready and tested to systematically finalize the development process.
