{"record":{"id":"b5a14c0df3b03e83","repo":"ipfs/kubo","slug":"building-fx-opts-w","errorCode":null,"errorMessage":"building fx opts: %w","messagePattern":"building fx opts: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/builder.go","lineNumber":84,"sourceCode":"\tctx, cancel := context.WithCancel(valueContext{ctx})\n\n\t// add a metrics scope.\n\tctx = metrics.CtxScope(ctx, \"ipfs\")\n\n\tn := &IpfsNode{\n\t\tctx: ctx,\n\t}\n\n\topts := []fx.Option{\n\t\tnode.IPFS(ctx, cfg),\n\t\tfx.NopLogger,\n\t}\n\tfor _, optFunc := range fxOptionFuncs {\n\t\tvar err error\n\t\topts, err = optFunc(FXNodeInfo{FXOptions: opts})\n\t\tif err != nil {\n\t\t\tcancel()\n\t\t\treturn nil, fmt.Errorf(\"building fx opts: %w\", err)\n\t\t}\n\t}\n\t//nolint:staticcheck // https://github.com/ipfs/kubo/pull/9423#issuecomment-1341038770\n\topts = append(opts, fx.Extract(n))\n\n\tapp := fx.New(opts...)\n\n\tvar once sync.Once\n\tvar stopErr error\n\tn.stop = func() error {\n\t\tonce.Do(func() {\n\t\t\t// Bound app.Stop with a deadline so an FX OnStop hook that\n\t\t\t// never returns cannot hang the daemon. ShutdownTimeout==0\n\t\t\t// opts out of the cap entirely and restores the legacy\n\t\t\t// behavior of waiting forever for hooks to complete. The\n\t\t\t// daemon's watchdog in cmd/ipfs/kubo/daemon.go fires at the\n\t\t\t// same deadline and is the unconditional os.Exit fallback.\n\t\t\tstopCtx := context.Background()","sourceCodeStart":66,"sourceCodeEnd":102,"githubUrl":"https://github.com/ipfs/kubo/blob/329838acdfafae224582930457efe80aa217afc0/core/builder.go#L66-L102","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nnode, err := core.NewNode(ctx, &core.BuildCfg{}, opts...) // opaque error\n// after\nif err != nil {\n    log.Errorf(\"node build failed: %+v\", err) // print full unwrap chain\n    if errors.Is(err, repo.ErrNoRepo) { /* init repo first */ }\n}","handlingStrategy":"try-catch","validationCode":"// pre-flight: ensure repo exists and is accessible before NewNode\nif err := repoApi.Err(); err != nil { /* init repo */ }\nif _, err := os.Stat(ipfsPath); err != nil {\n    return fmt.Errorf(\"repo missing, run ipfs init: %w\", err)\n}","typeGuard":"func isFxOptBuildError(err error) bool {\n    return err != nil && strings.Contains(err.Error(), \"building fx opts\")\n}","tryCatchPattern":"n, err := core.NewNode(ctx, &core.BuildCfg{}, opts...)\nif err != nil {\n    if isFxOptBuildError(err) {\n        cause := errors.Unwrap(err) // inspect failing option func\n        log.Errorf(\"fx option failed: %v\", cause)\n    }\n    cancel()\n    return err\n}","preventionTips":["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"],"tags":["node-construction","dependency-injection","fx"],"backgroundTag":"node-initialization-failed","analyzedSha":"329838acdfafae224582930457efe80aa217afc0","analyzedAt":"2026-09-03T18:30:52.135Z","contentChangedAt":"2026-09-03T18:30:52.135Z","schemaVersion":2},"datasetVersion":"2026-09-11T00:17:11.886Z"}