stacktrace: Index | Files | Directories

package stacktrace

import ""

Package stacktrace provides functions for wrapping an error to include line number and/or error code information.

A stacktrace produced by this package looks like this:

Failed to register for villain discovery
 --- at (ShieldAgent.reallyRegister) ---
 --- at (Connector.Register) ---
Caused by: Failed to load S.H.I.E.L.D. config from /opt/shield/conf/shield.yaml
 --- at (withShieldConfig) ---
Caused by: There isn't enough time (4 picoseconds required)
 --- at (PseudoResource.Adjust) ---
 --- at (reciprocatingPseudo.growDown) ---
 --- at (reciprocatingPseudo.verify) ---
Caused by: Inverse tachyon pulse failed
 --- at (TryPulse) ---

Note that stack traces are not designed to be user-visible. They can be valuable in a log file of a server application, but nobody wants to see one of them in CLI output or a web interface or a return value from library code.


Package Files

cause.go doc.go format.go stacktrace.go


var CleanPath = cleanpath.RemoveGoPath

CleanPath function is applied to file paths before adding them to a stacktrace. By default, it makes the path relative to the $GOPATH environment variable.

To remove some additional prefix like "" from file paths in stacktraces, use something like:

stacktrace.CleanPath = func(path string) string {
	path = cleanpath.RemoveGoPath(path)
	path = strings.TrimPrefix(path, "")
	return path
var DefaultFormat = FormatFull

DefaultFormat defines the behavior of err.Error() when called on a stacktrace, as well as the default behavior of the "%v", "%s" and "%q" formatting specifiers. By default, all of these produce a full stacktrace including line number information. To have them produce a condensed single-line output, set this value to stacktrace.FormatBrief.

The formatting specifier "%+s" can be used to force a full stacktrace regardless of the value of DefaultFormat. Similarly, the formatting specifier "%#s" can be used to force a brief output.

func NewError Uses

func NewError(msg string, vals ...interface{}) error

NewError is a drop-in replacement for fmt.Errorf that includes line number information. The canonical call looks like this:

if !IsOkay(arg) {
	return stacktrace.NewError("Expected %v to be okay", arg)

func NewErrorWithCode Uses

func NewErrorWithCode(code ErrorCode, msg string, vals ...interface{}) error

NewErrorWithCode is similar to NewError but also attaches an error code.

func NewMessageWithCode Uses

func NewMessageWithCode(code ErrorCode, msg string, vals ...interface{}) error

NewMessageWithCode returns an error that prints just like fmt.Errorf with no line number, but including a code. The error code mechanism can be useful by itself even where stack traces with line numbers are not warranted.

ttl := req.URL.Query().Get("ttl")
if ttl == "" {
	return 0, stacktrace.NewMessageWithCode(EcodeBadInput, "Missing ttl query parameter")

func Propagate Uses

func Propagate(cause error, msg string, vals ...interface{}) error

Propagate wraps an error to include line number information. The msg and vals arguments work like the ones for fmt.Errorf.

The message passed to Propagate should describe the action that failed, resulting in the cause. The canonical call looks like this:

result, err := process(arg)
if err != nil {
	return nil, stacktrace.Propagate(err, "Failed to process %v", arg)

To write the message, ask yourself "what does this call do?" What does process(arg) do? It processes ${arg}, so the message is that we failed to process ${arg}.

Pay attention that the message is not redundant with the one in err. If it is not possible to add any useful contextual information beyond what is already included in an error, msg can be an empty string:

func Something() error {
	defer mutex.Unlock()

	err := reallySomething()
	return stacktrace.Propagate(err, "")

If cause is nil, Propagate returns nil. This allows elision of some "if err != nil" checks.

func PropagateWithCode Uses

func PropagateWithCode(cause error, code ErrorCode, msg string, vals ...interface{}) error

PropagateWithCode is similar to Propagate but also attaches an error code.

_, err := os.Stat(manifestPath)
if os.IsNotExist(err) {
	return stacktrace.PropagateWithCode(err, EcodeManifestNotFound, "")

func RootCause Uses

func RootCause(err error) error

RootCause unwraps the original error that caused the current one.

_, err := f()
if perr, ok := stacktrace.RootCause(err).(*ParsingError); ok {
	showError(perr.Line, perr.Column, perr.Text)

type ErrorCode Uses

type ErrorCode uint16

ErrorCode is a code that can be attached to an error as it is passed/propagated up the stack.

There is no predefined set of error codes. You define the ones relevant to your application:

const (
	EcodeManifestNotFound = stacktrace.ErrorCode(iota)

The one predefined error code is NoCode, which has a value of math.MaxUint16. Avoid using that value as an error code.

An ordinary stacktrace.Propagate call preserves the error code of an error.

const NoCode ErrorCode = math.MaxUint16

NoCode is the error code of errors with no code explicitly attached.

func GetCode Uses

func GetCode(err error) ErrorCode

GetCode extracts the error code from an error.

for i := 0; i < attempts; i++ {
	err := Do()
	if stacktrace.GetCode(err) != EcodeTimeout {
		return err
	// try a few more times
return stacktrace.NewError("timed out after %d attempts", attempts)

GetCode returns the special value stacktrace.NoCode if err is nil or if there is no error code attached to err.

type Format Uses

type Format int

Format is the type of the two possible values of stacktrace.DefaultFormat.

const (
    // FormatFull means format as a full stacktrace including line number information.
    FormatFull Format = iota
    // FormatBrief means Format on a single line without line number information.



Package stacktrace imports 6 packages (graph) and is imported by 3 packages. Updated 2018-05-13. Refresh now. Tools for package owners.