ipfs/kubo · error

bootstrap address without a transport: %s

Error message

bootstrap address without a transport: %s

What it means

After confirming the multiaddr ends in a `/p2p` component, bootstrapAdd also checks that a transport part exists (`tpt == nil`). If SplitLeft consumed everything so no transport remains, the peer entry lacks a transport address and the command returns `bootstrap address without a transport: %s`.

Source

Thrown at core/commands/bootstrap.go:284

	return nil
}

func bootstrapAdd(r repo.Repo, cfg *config.Config, peers []string) ([]string, error) {
	// Validate peers - skip validation for "auto" placeholder
	for _, p := range peers {
		if p == config.AutoPlaceholder {
			continue // Skip validation for "auto" placeholder
		}
		m, err := ma.NewMultiaddr(p)
		if err != nil {
			return nil, err
		}
		tpt, p2ppart := ma.SplitLast(m)
		if p2ppart == nil || p2ppart.Protocol().Code != ma.P_P2P {
			return nil, fmt.Errorf("invalid bootstrap address: %s", p)
		}
		if tpt == nil {
			return nil, fmt.Errorf("bootstrap address without a transport: %s", p)
		}
	}

	addedMap := map[string]struct{}{}
	addedList := make([]string, 0, len(peers))

	// re-add cfg bootstrap peers to rm dupes
	bpeers := cfg.Bootstrap
	cfg.Bootstrap = nil

	// add new peers
	for _, s := range peers {
		if _, found := addedMap[s]; found {
			continue
		}

		cfg.Bootstrap = append(cfg.Bootstrap, s)
		addedList = append(addedList, s)

View on GitHub (pinned to 329838acdf)

Solutions

  1. Provide a full address with transport and peer ID: `/ip4/<ip>/tcp/<port>/p2p/<peerID>` or `/dnsaddr/<host>/p2p/<peerID>`
  2. Fetch the correct full address from `ipfs id` on the peer
  3. Check for a code/script bug that drops the transport portion of the multiaddr

Example fix

// before
ipfs bootstrap add /p2p/QmaCpDMG...
// after
ipfs bootstrap add /dnsaddr/bootstrap.libp2p.io/p2p/QmaCpDMG...
Defensive patterns

Strategy: validation

Validate before calling

func hasTransport(p string) bool {
    m, err := ma.NewMultiaddr(p)
    if err != nil { return false }
    tpt, last := ma.SplitLast(m)
    return last != nil && last.Protocol().Code == ma.P_P2P && tpt != nil
}

Type guard

null

Try / catch

if err != nil && strings.Contains(err.Error(), "without a transport") {
    // replace bare /p2p/<peerID> with a full transport address
}

Prevention

When it happens

Trigger: `ipfs bootstrap add` with an address consisting solely of the p2p component where a transport-bearing multiaddr is required by this code path, so SplitLast yields tpt==nil.

Common situations: Scripts that pass bare `/p2p/<peerID>` peer IDs where a full transport address is expected; address-building code that strips the transport when cleaning input.

Related errors


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