ipfs/kubo · error
cannot apply options to api without node
Error message
cannot apply options to api without node
What it means
NewCoreAPI returns a CoreAPI whose node may be unset; WithOptions copies the API with additional per-request options. Because options can affect node-backed behavior, applying them requires a node to exist. If api.nd is nil, this error is returned. Callers typically hit it when they construct a CoreAPI via the constructor that defers node binding and then call WithOptions before injecting the node.
Source
Thrown at core/coreapi/coreapi.go:158
func (api *CoreAPI) PubSub() coreiface.PubSubAPI {
return (*PubSubAPI)(api)
}
// Routing returns the RoutingAPI interface implementation backed by the kubo node
func (api *CoreAPI) Routing() coreiface.RoutingAPI {
return (*RoutingAPI)(api)
}
// WithOptions returns api with global options applied
func (api *CoreAPI) WithOptions(opts ...options.ApiOption) (coreiface.CoreAPI, error) {
settings := api.parentOpts // make sure to copy
_, err := options.ApiOptionsTo(&settings, opts...)
if err != nil {
return nil, err
}
if api.nd == nil {
return nil, errors.New("cannot apply options to api without node")
}
n := api.nd
subAPI := &CoreAPI{
nctx: n.Context(),
identity: n.Identity,
privateKey: n.PrivateKey,
repo: n.Repo,
blockstore: n.Blockstore,
baseBlocks: n.BaseBlocks,
pinning: n.Pinning,
blocks: n.Blocks,
dag: n.DAG,
ipldFetcherFactory: n.IPLDFetcherFactory,View on GitHub (pinned to 329838acdf)
Solutions
- Ensure the node is created and attached to the CoreAPI before calling WithOptions (create node first, then api.WithOptions)
- Use the standard kubo-as-a-library pattern: build the IpfsNode, then obtain the CoreAPI from it
- If you only need option validation, call options.ApiOptionsTo directly instead of WithOptions
- Check that the code path assigning api.nd actually ran (no early-return or error swallowed)
Example fix
// before
api := coreapi.NewCoreAPI(nil)
api2, err := api.WithOptions(opts...)
// after
nd, err := core.NewNode(ctx, &core.BuildCfg{})
api, err := coreapi.NewCoreAPI(nd)
api2, err := api.WithOptions(opts...) Defensive patterns
Strategy: validation
Validate before calling
if api == nil || api.nd == nil {
return errors.New("CoreAPI has no node attached; create the IpfsNode first")
}
_, err := api.WithOptions(opts...) Try / catch
api2, err := api.WithOptions(opts...)
if err != nil && strings.Contains(err.Error(), "cannot apply options to api without node") {
return fmt.Errorf("init order bug: build node before applying options: %w", err)
}
return api2, err Prevention
- Follow the kubo-as-a-library order: core.NewNode then coreapi/NewCoreAPI then WithOptions
- Never construct CoreAPI against a nil node in production code
- Add an assertion right after node creation in bootstrap code
When it happens
Trigger: Calling api.WithOptions(...) on a CoreAPI created without a node (nd == nil), e.g. a CoreAPI built for testing or one obtained before core.NewNode assignment.
Common situations: Library users embedding kubo-as-a-library who construct coreapi.NewCoreAPI(nil-ish contexts) and apply options before node creation; test harnesses that partially initialize the API; ordering mistakes in custom node bootstrap code.
Related errors
- expected env to be of type %T, got %T
- this dag node is a directory
- this dag node is not a regular file
- this action must be run in online mode, try running 'ipfs da
- operation not supported
AI-assisted analysis of ipfs/kubo@329838acdf (2026-09-03).
Data as JSON: /api/errors/5f861dab3e07536f.
Report an issue: GitHub.