ipfs/kubo · error

missing private key for node ID: %s

Error message

missing private key for node ID: %s

What it means

constructPeerHost builds the libp2p host and requires the node's private key to be present in the supplied peerstore. If ps.PrivKey(id) returns nil — the key was never added to the peerstore — host construction fails with this error naming the peer ID. It indicates the identity key was not loaded/injected into the peerstore before host construction.

Source

Thrown at core/node/libp2p/hostopt.go:20

import (
	"fmt"

	"github.com/libp2p/go-libp2p"
	"github.com/libp2p/go-libp2p/core/host"
	"github.com/libp2p/go-libp2p/core/peer"
	"github.com/libp2p/go-libp2p/core/peerstore"
)

type HostOption func(id peer.ID, ps peerstore.Peerstore, options ...libp2p.Option) (host.Host, error)

var DefaultHostOption HostOption = constructPeerHost

// isolates the complex initialization steps
func constructPeerHost(id peer.ID, ps peerstore.Peerstore, options ...libp2p.Option) (host.Host, error) {
	pkey := ps.PrivKey(id)
	if pkey == nil {
		return nil, fmt.Errorf("missing private key for node ID: %s", id)
	}
	options = append([]libp2p.Option{libp2p.Identity(pkey), libp2p.Peerstore(ps)}, options...)
	return libp2p.New(options...)
}

View on GitHub (pinned to 329838acdf)

Solutions

  1. Ensure the private key is added to the peerstore before constructing the host: `ps.AddPrivKey(id, sk)` where sk is parsed from cfg.Identity.PrivKey
  2. When using libp2p.New directly, pass libp2p.Identity(sk) so the host injects the key itself
  3. In kubo, verify identity loading succeeded upstream (no prior errors about Identity.PrivKey) and that you are not constructing a host with an empty/temporary peerstore

Example fix

// before
h, err := constructPeerHost(id, peerstore.NewPeerstore())
// after
ps := peerstore.NewPeerstore()
ps.AddPrivKey(id, sk)
h, err := constructPeerHost(id, ps)
Defensive patterns

Strategy: type-guard

Validate before calling

if ps.PrivKey(id) == nil {
    return fmt.Errorf("peerstore missing private key for %s; add via ps.AddPrivKey(id, sk) or libp2p.Identity(sk)", id)
}

Type guard

func hasIdentityKey(ps peerstore.Peerstore, id peer.ID) bool { return ps.PrivKey(id) != nil }

Prevention

When it happens

Trigger: Calling constructPeerHost (DefaultHostOption) with a peerstore that lacks the entry for the given peer ID — e.g. an embedder building a host manually without adding the identity key via ps.AddPrivKey, or identity loading failing upstream in the fx graph.

Common situations: kubo-as-a-library embedders constructing a libp2p host with a fresh peerstore but forgetting libp2p.Identity or peerstore injection; identity config load errors that were swallowed upstream; test harnesses passing an empty peerstore.

Related errors


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