ipfs/kubo · error
building fx opts: %w
Error message
building fx opts: %w
What it means
NewNode in core/builder.go builds the fx dependency-injection options by running each user-supplied fxOptionFunc; if any of these callback functions returns an error, node construction aborts and the error is wrapped with 'building fx opts'. The wrapped error comes from the specific option func (e.g. plugins, repo inspection, host setup), so inspect the %w chain for the root cause.
Source
Thrown at core/builder.go:84
ctx, cancel := context.WithCancel(valueContext{ctx})
// add a metrics scope.
ctx = metrics.CtxScope(ctx, "ipfs")
n := &IpfsNode{
ctx: ctx,
}
opts := []fx.Option{
node.IPFS(ctx, cfg),
fx.NopLogger,
}
for _, optFunc := range fxOptionFuncs {
var err error
opts, err = optFunc(FXNodeInfo{FXOptions: opts})
if err != nil {
cancel()
return nil, fmt.Errorf("building fx opts: %w", err)
}
}
//nolint:staticcheck // https://github.com/ipfs/kubo/pull/9423#issuecomment-1341038770
opts = append(opts, fx.Extract(n))
app := fx.New(opts...)
var once sync.Once
var stopErr error
n.stop = func() error {
once.Do(func() {
// Bound app.Stop with a deadline so an FX OnStop hook that
// never returns cannot hang the daemon. ShutdownTimeout==0
// opts out of the cap entirely and restores the legacy
// behavior of waiting forever for hooks to complete. The
// daemon's watchdog in cmd/ipfs/kubo/daemon.go fires at the
// same deadline and is the unconditional os.Exit fallback.
stopCtx := context.Background()View on GitHub (pinned to 329838acdf)
Solutions
- Read the wrapped (%w) cause with errors.Unwrap/errors.Is to find the failing option func.
- Check repo integrity and datastore availability (ipfs repo fsck, disk space, permissions).
- Fix or remove the failing fx option func in the node construction call.
Example fix
// before
node, err := core.NewNode(ctx, &core.BuildCfg{}, opts...) // opaque error
// after
if err != nil {
log.Errorf("node build failed: %+v", err) // print full unwrap chain
if errors.Is(err, repo.ErrNoRepo) { /* init repo first */ }
} Defensive patterns
Strategy: try-catch
Validate before calling
// pre-flight: ensure repo exists and is accessible before NewNode
if err := repoApi.Err(); err != nil { /* init repo */ }
if _, err := os.Stat(ipfsPath); err != nil {
return fmt.Errorf("repo missing, run ipfs init: %w", err)
} Type guard
func isFxOptBuildError(err error) bool {
return err != nil && strings.Contains(err.Error(), "building fx opts")
} Try / catch
n, err := core.NewNode(ctx, &core.BuildCfg{}, opts...)
if err != nil {
if isFxOptBuildError(err) {
cause := errors.Unwrap(err) // inspect failing option func
log.Errorf("fx option failed: %v", cause)
}
cancel()
return err
} Prevention
- Ensure each FXOption func returns nil error on happy path and wraps real causes with %w
- Init the repo (ipfs init) before constructing an online node in library code
- Check datastore/disk availability in deployment health checks
When it happens
Trigger: Calling core.NewNode with FXOption funcs that fail — e.g. an fx option that opens the repo/blockstore and hits a corrupted datastore, or a plugin-loading option that errors.
Common situations: Embedding kubo as a library (kubo-as-a-library examples); daemon startup failing on repo/datastore issues surfaced by an option func; custom integrations passing faulty options.
Related errors
- constructing the node (see log for full detail): %w
- serveHTTPApi: ConstructNode() failed: %s
- serveHTTPGateway: ConstructNode() failed: %s
- serveHTTPGatewayOverLibp2p: ConstructNode() failed: %s
- cannot create libp2p gateway: node PeerHost is nil (this sho
AI-assisted analysis of ipfs/kubo@329838acdf (2026-09-03).
Data as JSON: /api/errors/b5a14c0df3b03e83.
Report an issue: GitHub.