fix(core/node): unwrap fx error in node construction
Lucas Molas committed
Jan 5, 2022 at 11:25 UTC
519863ecab4db26d33d9a4af8f5284acf4b5ca29
4 files changed
+51
-4
cmd/ipfs/daemon.go
-1
@@ -427,7 +427,6 @@ func daemonFunc(req *cmds.Request, re cmds.ResponseEmitter, env cmds.Environment
427
428
node, err := core.NewNode(req.Context, ncfg)
429
if err != nil {
430
- log.Error("error from node construction: ", err)
430
return err
431
}
432
node.IsDaemon = true
core/builder.go
+48
-2
@@ -2,6 +2,8 @@ package core
2
3
import (
4
"context"
5
+ "fmt"
6
+ "reflect"
7
"sync"
8
"time"
9
@@ -9,6 +11,7 @@ import (
11
"github.com/ipfs/go-ipfs/core/node"
12
13
"github.com/ipfs/go-metrics-interface"
14
+ "go.uber.org/dig"
15
"go.uber.org/fx"
16
)
17
@@ -75,11 +78,11 @@ func NewNode(ctx context.Context, cfg *BuildCfg) (*IpfsNode, error) {
78
}()
79
80
if app.Err() != nil {
78
- return nil, app.Err()
81
+ return nil, logAndUnwrapFxError(app.Err())
82
}
83
84
if err := app.Start(ctx); err != nil {
82
- return nil, err
85
+ return nil, logAndUnwrapFxError(err)
86
}
87
88
// TODO: How soon will bootstrap move to libp2p?
@@ -89,3 +92,46 @@ func NewNode(ctx context.Context, cfg *BuildCfg) (*IpfsNode, error) {
92
93
return n, n.Bootstrap(bootstrap.DefaultBootstrapConfig)
94
}
95
+
96
+// Log the entire `app.Err()` but return only the innermost one to the user
97
+// given the full error can be very long (as it can expose the entire build
98
+// graph in a single string).
99
+//
100
+// The fx.App error exposed through `app.Err()` normally contains un-exported
101
+// errors from its low-level `dig` package:
102
+// * https://github.com/uber-go/dig/blob/5e5a20d/error.go#L82
103
+// These usually wrap themselves in many layers to expose where in the build
104
+// chain did the error happen. Although useful for a developer that needs to
105
+// debug it, it can be very confusing for a user that just wants the IPFS error
106
+// that he can probably fix without being aware of the entire chain.
107
+// Unwrapping everything is not the best solution as there can be useful
108
+// information in the intermediate errors, mainly in the next to last error
109
+// that locates which component is the build error coming from, but it's the
110
+// best we can do at the moment given all errors in dig are private and we
111
+// just have the generic `RootCause` API.
112
+func logAndUnwrapFxError(fxAppErr error) error {
113
+ if fxAppErr == nil {
114
+ return nil
115
+ }
116
+
117
+ log.Error("constructing the node: ", fxAppErr)
118
+
119
+ err := fxAppErr
120
+ for {
121
+ extractedErr := dig.RootCause(err)
122
+ // Note that the `RootCause` name is misleading as it just unwraps only
123
+ // *one* error layer at a time, so we need to continuously call it.
124
+ if !reflect.TypeOf(extractedErr).Comparable() {
125
+ // Some internal errors are not comparable (e.g., `dig.errMissingTypes`
126
+ // which is a slice) and we can't go further.
127
+ break
128
+ }
129
+ if extractedErr == err {
130
+ // We didn't unwrap any new error in the last call, reached the innermost one.
131
+ break
132
+ }
133
+ err = extractedErr
134
+ }
135
+
136
+ return fmt.Errorf("constructing the node (see log for full detail): %w", err)
137
+}
go.mod
+1
@@ -104,6 +104,7 @@ require (
104
github.com/whyrusleeping/go-sysinfo v0.0.0-20190219211824-4a357d4b90b1
105
github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7
106
go.opencensus.io v0.23.0
107
+ go.uber.org/dig v1.14.0
108
go.uber.org/fx v1.16.0
109
go.uber.org/zap v1.21.0
110
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519
go.sum
+2
-1
@@ -1418,8 +1418,9 @@ go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
1418
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
1419
go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE=
1420
go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
1421
-go.uber.org/dig v1.12.0 h1:l1GQeZpEbss0/M4l/ZotuBndCrkMdjnygzgcuOjAdaY=
1421
go.uber.org/dig v1.12.0/go.mod h1:X34SnWGr8Fyla9zQNO2GSO2D+TIuqB14OS8JhYocIyw=
1422
+go.uber.org/dig v1.14.0 h1:VmGvIH45/aapXPQkaOrK5u4B5B7jxZB98HM/utx0eME=
1423
+go.uber.org/dig v1.14.0/go.mod h1:jHAn/z1Ld1luVVyGKOAIFYz/uBFqKjjEEdIqVAqfQ2o=
1424
go.uber.org/fx v1.16.0 h1:N8i80+X1DCX+qMRiKzM+jPPZiIiyK/bVCysga3+B+1w=
1425
go.uber.org/fx v1.16.0/go.mod h1:OMoT5BnXcOaiexlpjtpE4vcAmzyDKyRs9TRYXCzamx8=
1426
go.uber.org/goleak v1.0.0/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A=