package aerrors import ( "errors" "fmt" "github.com/filecoin-project/specs-actors/actors/runtime/exitcode" cbor "github.com/ipfs/go-ipld-cbor" "golang.org/x/xerrors" ) // New creates a new non-fatal error func New(retCode exitcode.ExitCode, message string) ActorError { if retCode == 0 { return &actorError{ fatal: true, retCode: 0, msg: "tried creating an error and setting RetCode to 0", frame: xerrors.Caller(1), err: errors.New(message), } } return &actorError{ retCode: retCode, msg: message, frame: xerrors.Caller(1), } } // Newf creates a new non-fatal error func Newf(retCode exitcode.ExitCode, format string, args ...interface{}) ActorError { if retCode == 0 { return &actorError{ fatal: true, retCode: 0, msg: "tried creating an error and setting RetCode to 0", frame: xerrors.Caller(1), err: fmt.Errorf(format, args...), } } return &actorError{ retCode: retCode, msg: fmt.Sprintf(format, args...), frame: xerrors.Caller(1), } } // todo: bit hacky func NewfSkip(skip int, retCode exitcode.ExitCode, format string, args ...interface{}) ActorError { if retCode == 0 { return &actorError{ fatal: true, retCode: 0, msg: "tried creating an error and setting RetCode to 0", frame: xerrors.Caller(skip), err: fmt.Errorf(format, args...), } } return &actorError{ retCode: retCode, msg: fmt.Sprintf(format, args...), frame: xerrors.Caller(skip), } } func Fatal(message string, args ...interface{}) ActorError { return &actorError{ fatal: true, msg: message, frame: xerrors.Caller(1), } } func Fatalf(format string, args ...interface{}) ActorError { return &actorError{ fatal: true, msg: fmt.Sprintf(format, args...), frame: xerrors.Caller(1), } } // Wrap extens chain of errors with a message func Wrap(err ActorError, message string) ActorError { if err == nil { return nil } return &actorError{ fatal: IsFatal(err), retCode: RetCode(err), msg: message, frame: xerrors.Caller(1), err: err, } } // Wrapf extens chain of errors with a message func Wrapf(err ActorError, format string, args ...interface{}) ActorError { if err == nil { return nil } return &actorError{ fatal: IsFatal(err), retCode: RetCode(err), msg: fmt.Sprintf(format, args...), frame: xerrors.Caller(1), err: err, } } // Absorb takes and error and makes in not fatal ActorError func Absorb(err error, retCode exitcode.ExitCode, msg string) ActorError { if err == nil { return nil } if aerr, ok := err.(ActorError); ok && IsFatal(aerr) { return &actorError{ fatal: true, retCode: 0, msg: "tried absorbing an error that is already a fatal error", frame: xerrors.Caller(1), err: err, } } if retCode == 0 { return &actorError{ fatal: true, retCode: 0, msg: "tried absorbing an error and setting RetCode to 0", frame: xerrors.Caller(1), err: err, } } return &actorError{ fatal: false, retCode: retCode, msg: msg, frame: xerrors.Caller(1), err: err, } } // Escalate takes and error and escalates it into a fatal error func Escalate(err error, msg string) ActorError { if err == nil { return nil } return &actorError{ fatal: true, msg: msg, frame: xerrors.Caller(1), err: err, } } func HandleExternalError(err error, msg string) ActorError { if err == nil { return nil } if aerr, ok := err.(ActorError); ok { return &actorError{ fatal: IsFatal(aerr), retCode: RetCode(aerr), msg: msg, frame: xerrors.Caller(1), err: aerr, } } if xerrors.Is(err, &cbor.SerializationError{}) { return &actorError{ fatal: false, retCode: 253, msg: msg, frame: xerrors.Caller(1), err: err, } } return &actorError{ fatal: false, retCode: 219, msg: msg, frame: xerrors.Caller(1), err: err, } }