Between a rock and a crazy place

go stacktraces


Let's say you write a library in go and want an easy way to get debugging information from your users. Sure, you return errors from everything, but it is sometimes hard to pinpoint where a particular error occured and what caused it. If your package panics, that will give you a stacktrace, but as you probably know you shouldn't panic in case of an error, but just gracefull recover and return the error to your caller.

I recently discovered a pattern which I am quite happy with (for now). You can include a stacktrace when returning an error. If you disable this behaviour by default you should have as good as no impact for normal users, while making it much easier to debug problems. Neat.

package awesomelib

import (

type tracedError struct {
    err   error
    trace string

var (
    stacktrace bool
    traceSize = 16*1024

func init() {
    if os.Getenv("AWESOMELIB_ENABLE_STACKTRACE") == "true" {
        stacktrace = true

func wrapErr(err error) error {
    // If stacktraces are disabled, we return the error as is
    if !stacktrace {
        return err

    // This is a convenience, so that we can just throw a wrapErr at every
    // point we return an error and don't get layered useless wrappers
    if Err, ok := err.(*tracedError); ok {
        return Err

    buf := make([]byte, traceSize)
    n := runtime.Stack(buf, false)
    return &tracedError{ err: err, trace: string(buf[:n]) }

func (err *tracedError) Error() string {
    return fmt.Sprintf("%v\n%s", err.err, err.trace)

func DoFancyStuff(path string) error {
    file, err := os.Open(path)
    if err != nil {
        return wrapErr(err)
    // fancy stuff