Error handling
==============

General Overview
----------------
Hyperledger Fabric code should use the vendored package
**github.com/pkg/errors** in place of the standard error type provided by Go.
This package allows easy generation and display of stack traces with error
messages.

Usage Instructions
------------------

**github.com/pkg/errors** should be used in place of all calls to
``fmt.Errorf()`` or ``errors.New()``. Using this package will generate a
call stack that will be appended to the error message.

Using this package is simple and will only require easy tweaks to your code.

First, you'll need to import **github.com/pkg/errors**.

Next, update all errors that are generated by your code to use one of the error
creation functions (errors.New(), errors.Errorf(), errors.WithMessage(),
errors.Wrap(), errors.Wrapf().

.. note:: See https://godoc.org/github.com/pkg/errors for complete documentation
          of the available error creation function. Also, refer to the General guidelines
          section below for more specific guidelines for using the package for Fabric
          code.

Finally, change the formatting directive for any logger or fmt.Printf() calls
from ``%s`` to ``%+v`` to print the call stack along with the error message.

General guidelines for error handling in Hyperledger Fabric
-----------------------------------------------------------

- If you are servicing a user request, you should log the error and return it.
- If the error comes from an external source, such as a Go library or vendored
  package, wrap the error using errors.Wrap() to generate a call stack for the
  error.
- If the error comes from another Fabric function, add further context, if
  desired, to the error message using errors.WithMessage() while leaving the
  call stack unaffected.
- A panic should not be allowed to propagate to other packages.

Example program
---------------

The following example program provides a clear demonstration of using the
package:

.. code:: go

  package main

  import (
    "fmt"

    "github.com/pkg/errors"
  )

  func wrapWithStack() error {
    err := createError()
    // do this when error comes from external source (go lib or vendor)
    return errors.Wrap(err, "wrapping an error with stack")
  }
  func wrapWithoutStack() error {
    err := createError()
    // do this when error comes from internal Fabric since it already has stack trace
    return errors.WithMessage(err, "wrapping an error without stack")
  }
  func createError() error {
    return errors.New("original error")
  }

  func main() {
    err := createError()
    fmt.Printf("print error without stack: %s\n\n", err)
    fmt.Printf("print error with stack: %+v\n\n", err)
    err = wrapWithoutStack()
    fmt.Printf("%+v\n\n", err)
    err = wrapWithStack()
    fmt.Printf("%+v\n\n", err)
  }

.. Licensed under Creative Commons Attribution 4.0 International License
   https://creativecommons.org/licenses/by/4.0/
