Skip to content

fix: empty Bootstrap list no longer dials stale backup peers - #11453

Draft
karawitan wants to merge 1 commit into
ipfs:masterfrom
karawitan:fix/bootstrap-skip-when-routing-none
Draft

fix: empty Bootstrap list no longer dials stale backup peers#11453
karawitan wants to merge 1 commit into
ipfs:masterfrom
karawitan:fix/bootstrap-skip-when-routing-none

Conversation

@karawitan

@karawitan karawitan commented Sep 6, 2026

Copy link
Copy Markdown

Summary

Rework of this PR per @lidel's review in #11453 (review). The fix belongs in boxo (bootstrap.bootstrapRound skips the backup list when no bootstrap peers are configured), not behind a Routing.Type=none guard in kubo. This PR is now the companion kubo PR for ipfs/boxo#1213.

What changed here

  • go.mod / go.sum: pin the boxo fix via a temporary replace directive pointing at the boxo PR branch (karawitan/boxo@76cf61a). Once ipfs/boxo#1213 merges, this repoints at boxo main and converts to a pseudo-version pin.
  • core/core_test.go: add TestBootstrapWithEmptyPeerListAndStaleBackupPeers, a kubo-level regression test for #11452. It verifies IpfsNode.Bootstrap runs without error with an empty Bootstrap config and a populated TempBootstrapPeersKey (stale backup peers from a previous run), and starts a bootstrapper whose rounds are no-ops for the backup list. The dialing behavior itself is fixed and unit-tested in boxo.
  • docs/config.md: document under Bootstrap that an empty list disables all bootstrap dialing, including saved backup peers. Note that Peering.Peers and mDNS are independent and may still dial. (Reverts the overpromising Routing.Type=none wording from the original PR — Peering.Peers and mDNS still dial regardless.)
  • docs/changelogs/v0.44.md: add a v0.44 highlight. Drops the v0.43 entry (already released) and the broken emoji from the original PR.

What was removed from the original PR

  • The Routing.Type=none guard in core/core.go is gone. Per lidel: Routing.Type and Bootstrap are separate settings; some users run Routing.Type=none with their own Bootstrap peers (private/static swarms), and the guard would silently break those. The guard also missed ipfs daemon --routing=none, which overrides routing at runtime without changing the config file.
  • The TestBootstrapSkippedWhenRoutingNone test is replaced by TestBootstrapWithEmptyPeerListAndStaleBackupPeers.

Behavior change

Previously, a node with default routing and an empty Bootstrap list would still dial backup peers persisted from previous runs. After this change (boxo fix), it does not. This aligns behavior with operator intent: an empty Bootstrap list now means "no bootstrap dialing at all, including saved backup peers." Nodes that configure explicit Bootstrap peers are unaffected; the backup-list fallback still runs when those peers fail to connect.

Test plan

  • go test ./core/ -run TestBootstrapWithEmptyPeerListAndStaleBackupPeers -v -count=1 passes
  • go test ./core/ -count=1 passes (all existing core tests green)
  • go vet ./core/... passes
  • gofmt -l core/ clean
  • make mod_tidy run (all three go.mod files tidied)
  • Kubo CI green (this PR is a draft while it pins the unmerged boxo branch ipfs/boxo#1213)

References

Generated with Devin

@lidel lidel left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for digging into this. The root cause you found is right. The fix needs more work.

Feels like a wrong place: Routing.Type and Bootstrap are two separate settings. Some people run Routing.Type=none together with their own Bootstrap peers (private or static setups), and with this change those nodes would never connect. The check also misses ipfs daemon --routing=none, since that flag does not change the config file.

The backup peer list exists so a node can recover when its configured bootstrap peers are down (#8856). If Bootstrap is empty, there is nothing to recover from, so the backup list should not be used at all. The simplest fix is in boxo, in bootstrap.bootstrapRound: when cfg.BootstrapPeers() returns nothing, stop there instead of trying the backup list. That covers your Bootstrap: null case (it becomes an empty list), works with the --routing flag, and keeps none + explicit bootstrap peers working. No new config option is needed.

If you open that change against ipfs/boxo, this PR can become: the boxo bump, the changelog line, and one sentence under Bootstrap in docs/config.md saying that an empty list turns off all bootstrap dialing, including saved backup peers.

Two smaller things: the changelog entry landed in v0.43.md (already released) instead of v0.44.md, and both files now have a broken emoji () in the headings, probably from the editor's encoding. The new config.md wording "will not attempt to dial any external peers" also promises too much, since Peering.Peers and mDNS still dial.

Hope this helps.

ps. since this should be v0.44, be mindful it may take some time before new maintainer is identified and picks this up

Rework of ipfs#11453 per maintainer review (lidel): the fix belongs in
boxo (bootstrap.bootstrapRound skips the backup list when no
bootstrap peers are configured), not behind a Routing.Type=none guard
in kubo. This PR is now the companion to ipfs/boxo#1213:

- Pin the boxo fix via a temporary replace directive pointing at the
  boxo PR branch. Once ipfs/boxo#1213 merges, repoint at boxo main
  and convert to a pseudo-version pin.
- Add a kubo-level regression test
  (TestBootstrapWithEmptyPeerListAndStaleBackupPeers) verifying
  IpfsNode.Bootstrap runs with an empty Bootstrap config and a
  populated TempBootstrapPeersKey without error.
- Document under Bootstrap in docs/config.md that an empty list
  disables all bootstrap dialing, including saved backup peers.
- Add a v0.44 changelog highlight. Drop the v0.43 entry and the
  broken emoji from the original PR.

Closes ipfs#11452

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
@karawitan
karawitan force-pushed the fix/bootstrap-skip-when-routing-none branch from 4a03e7e to 9446212 Compare September 7, 2026 07:19
@karawitan karawitan changed the title fix: skip bootstrap when Routing.Type=none fix: empty Bootstrap list no longer dials stale backup peers Sep 7, 2026
@karawitan
karawitan marked this pull request as draft September 7, 2026 07:19
@karawitan

Copy link
Copy Markdown
Author

Thanks @lidel — reworked this PR per your review.

Fix moved to boxo: ipfs/boxo#1213 adds an early return in bootstrap.bootstrapRound when cfg.BootstrapPeers() is empty, before consulting the backup list. That covers the Bootstrap: null case, works with ipfs daemon --routing=none (runtime override, no config change), and keeps Routing.Type=none + explicit Bootstrap peers working. Two boxo tests pin both sides: backup list is not consulted when no peers are configured, and is still consulted when configured peers fail to connect (#8856 recovery preserved).

This PR is now the companion kubo PR for ipfs/boxo#1213:

  • go.mod pins the boxo branch via a temporary replace (repointed to main as a pseudo-version once the boxo PR merges).
  • core/core_test.go adds TestBootstrapWithEmptyPeerListAndStaleBackupPeers — a kubo-level regression test that seeds TempBootstrapPeersKey with stale peers and verifies IpfsNode.Bootstrap runs without error with an empty Bootstrap config.
  • docs/config.md documents under Bootstrap that an empty list disables all bootstrap dialing, including saved backup peers, and notes Peering.Peers and mDNS are independent. The overpromising Routing.Type=none wording is gone.
  • Changelog moved to v0.44; the broken emoji and the v0.43 entry are dropped.

Marked as draft while it pins the unmerged boxo branch.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Routing.Type=none still runs bootstrap process, dials stale backup peers and triggers external DNS resolution

2 participants