Open-source project
maruel/panicparse avatar
maruel/panicparse

panicparse: reading Go crash dumps without drowning in goroutines

Crash your app in style (Golang)

3,707 stars103 forksGoApache-2.0

At a glance

What is it?
panicparse is a Go stack trace parser that groups identical goroutines, shortens pointer values and pushes standard library frames out of the way. It is a command line filter and a library, and it is most useful when a crash prints hundreds of stacks.
Who is it for?
Adopt panicparse if your Go services or test suites crash with long multi-goroutine dumps and you already read them by hand. Do not adopt it if you need a profiler, a tracing backend or continuous crash reporting; it is a parser for text that already exists, not a collector.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 80 days ago.
What is it written in?
Mainly Go, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What panicparse does to a Go panic dump

A Go program that panics with GOTRACEBACK=all prints one stack per goroutine. On a server with hundreds of connections, that is a wall of near-identical text where the one goroutine that actually caused the crash is buried somewhere in the middle. panicparse reads that text and rewrites it.

The README describes the core behaviour plainly: it parses panic stack traces, then densifies and deduplicates goroutines with similar stack traces. Three things follow from that. Identical stacks collapse into a single entry with a count. Pointer arguments are printed as pointer IDs rather than raw addresses, so two runs of the same bug look alike. Stacks that contain only standard library frames are pushed to the bottom, which leaves your own code at the top. The project claims more than 50 percent more compact output than the original dump while being more readable.

The audience is narrow and specific: Go developers debugging crashes and deadlocks in heavily parallelized programs. If your program has one goroutine, this tool has nothing to do. If it has thousands, the deduplication is the entire value.

How the parser, the CLI and webstack fit together

The repository is organised around a library rather than a single binary. The stack/ directory holds the parser and the snapshot types, cmd/ holds the pp command, and internal/ holds shared code. main.go sits at the top level. The go.mod declares module github.com/maruel/panicparse/v2 and requires github.com/google/go-cmp, github.com/mattn/go-colorable, github.com/mattn/go-isatty, github.com/mgutz/ansi and golang.org/x/sys. The isatty and colorable dependencies are there so colour output is suppressed when stdout is not a terminal, which matters when you pipe dumps into files.

Two entry points are documented beyond the CLI. The first is an HTTP handler middleware, exposed as an example package at github.com/maruel/panicparse/v2/stack#example-package-HttpHandlerMiddleware. The second is webstack.SnapshotHandler, an http.Handler that serves a snapshot of your goroutines. The README compares it directly to net/http/pprof and calls it much more readable. That is a design opinion, not a measurement, but it is the reason the package exists: pprof gives you a profiler's view, webstack gives you a grouped list.

The parser also reads source files when they are available on disk, to augment the output. That is why running pp on a dump produced on a different machine, or inside a container without the source tree, gives you less than running it where the binary was built.

Installing pp and parsing your first dump

Installation is a single Go install command, and Go 1.17 or newer is required. The README points older toolchains at v2.3.1.

bash
go install github.com/maruel/panicparse/v2/cmd/pp@latest

The binary lands in $GOPATH/bin. There is a naming trap documented in the README: some systems already have a /usr/bin/pp from the Perl PAR Packager, which prints things like "Creating tables and indexes..." and "/usr/bin/pp5.18: No input files specified". If you hit that, either put $GOPATH/bin first on your PATH or install and call the long name instead.

bash
go install github.com/maruel/panicparse/v2@latest
go test 2> panicparse

The practical first use is piping a test run through it. Go's panic output goes to stderr through the runtime's print function, so the shell has to merge the two streams. On bash 4 or zsh, |& does that; on Windows or macOS's stock bash 3.2, use the long form.

bash
go test -v 2>&1 | pp

What you should see is the same stack trace, regrouped: repeated goroutines merged with a count, standard library only stacks moved to the bottom. pp streams stdin to stdout until it detects a panic, so it does not interfere with normal output. You can also write a dump to a file and parse it later.

bash
go test 2> stack.txt
pp stack.txt

One setting changes how much there is to parse. GOTRACEBACK defaults to single, which means a panic prints only the crashing goroutine. To get every goroutine, the README says to export GOTRACEBACK=all, and suggests putting it in your .bashrc.

The inlining trade-off and what the README leaves out

The README's own tips section concedes a real limitation: the Go toolchain inlines functions, and inlined frames make traces less informative, while optimisation interferes with traces. The suggested workaround is to rebuild with -gcflags '-N -l'.

bash
go test -gcflags '-N -l' ./... |& pp

That is a genuine trade-off, not a footnote. A binary built with those flags is not the binary you ship, so the trace you are reading may not match production behaviour. You get clearer frames at the cost of debugging a differently compiled program.

Other gaps are worth naming. The README does not document how to configure the webstack handler, only that it exists and is an http.Handler. It does not describe the HTML export's options, the colour scheme, or any way to change how aggressively goroutines are deduplicated. There is no documented rollback or version pinning advice beyond the note that older Go versions should use v2.3.1. And PowerShell is explicitly a rough edge: the README calls its 2>&1 redirection broken and says the workaround is to shell out to cmd.exe.

The parser is also text-driven. It reads Go's panic format, so a crash that never reaches that format, such as a segfault in cgo code or an OOM kill by the kernel, produces nothing for pp to parse.

panicparse compared with net/http/pprof

The obvious alternative for a running Go service is net/http/pprof, which the README names directly when describing webstack.SnapshotHandler. The difference is in what each exposes and when.

pprof is a profiler. You attach to a live process, collect CPU or heap or goroutine profiles over a sampling window, and analyse them, often through go tool pprof. It answers questions about where time or memory is going across a period of execution. panicparse answers a different question: what did the process print at the moment it died, and which of those hundreds of goroutine stacks are the same. It works on a text dump, which means it works after the fact, on a file, on a CI log, with no live process to attach to.

That also defines when panicparse is the wrong tool. If the process is still running and you want to know why it is slow, pprof is the instrument. If you want crash reports aggregated across many machines, panicparse does not collect anything; it is a parser and a library you would have to wire into your own reporting path. And if the crash dump is small, a single goroutine and a dozen frames, the deduplication and the pointer ID rewriting buy you almost nothing.

Licence, releases and what maintenance costs you

The project is Apache-2.0, which permits commercial and closed source use and includes an explicit patent grant. That matters here because the stack/ package is meant to be imported into your own code, not just run as a binary. If you embed it, you carry the usual Apache-2.0 obligations around notices and attribution. This is a description of the licence text, not legal advice; check it against your own distribution model.

The release history is uneven. v2.3.0 and v2.3.1 landed in mid and late 2022, v2.4.0 in November 2024, and the last push to the repository was on 2026-07-13. So the code is not abandoned, but the tagged releases do not track every commit; if you need a specific fix, you may be pulling from main rather than from a tag.

The dependency surface is small and stable: go-cmp, go-colorable, go-isatty, mgutz/ansi and golang.org/x/sys. The module declares go 1.23.0, while the README's floor for the tool itself is go1.17. Upgrading Go versions is the main ongoing cost, since the parser tracks the runtime's panic output format. A change to that format in a future Go release is the realistic breakage scenario, and it would show up as frames that no longer group correctly rather than as a build failure.

Editorial conclusion

Adopt panicparse if your Go services or test suites crash with long multi-goroutine dumps and you already read them by hand. Do not adopt it if you need a profiler, a tracing backend or continuous crash reporting; it is a parser for text that already exists, not a collector. Before relying on it, verify two things on a real dump from your own binary: that GOTRACEBACK is set to all so the dump contains every goroutine, and that the pp binary on your PATH is the Go one from github.com/maruel/panicparse/v2/cmd/pp and not the Perl PAR Packager that also installs as pp. Then check whether your release builds should keep inlining disabled with -gcflags '-N -l', because the README notes that inlining makes traces less informative and that optimization interferes with them.

Frequently asked questions

Does panicparse work on Windows, macOS and Linux?

Yes. The README states it works on any platform supported by Go, including Windows, macOS and linux, and that it has full go module support. The shell syntax for merging stderr into the pipe differs per platform.

Why does pp print "No input files specified" instead of parsing my trace?

You are probably running the Perl PAR Packager, which also installs a binary called pp. The README suggests putting $GOPATH/bin at the beginning of $PATH, or installing and invoking the long name panicparse instead.

Which Go version does panicparse require?

The README says it requires go1.17 or newer and points older Go versions at v2.3.1. The go.mod in the repository declares go 1.23.0.

How do I get every goroutine in the dump instead of just the crashing one?

Set the GOTRACEBACK environment variable to all. By default it is single, which returns only the current goroutine trace, and the README suggests exporting GOTRACEBACK=all, possibly in your .bashrc.

Official sources

  1. License: Apache-2.0
  2. maruel/panicparse on GitHub
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/maruel-panicparse.svg)](https://hysenlabs.com/projects/maruel-panicparse)