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

  1. Ensure the node is created and attached to the CoreAPI before calling WithOptions (create node first, then api.WithOptions)
  2. Use the standard kubo-as-a-library pattern: build the IpfsNode, then obtain the CoreAPI from it
  3. If you only need option validation, call options.ApiOptionsTo directly instead of WithOptions
  4. 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

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


AI-assisted analysis of ipfs/kubo@329838acdf (2026-09-03). Data as JSON: /api/errors/5f861dab3e07536f. Report an issue: GitHub.