ipfs / ipfs/kubo

Kubo drops freshly published IPNS records when using custom HTTP routers (no bootstrap)

Open
#11,003 7 comments 0 reactions 1 assignee Claimed by @guillaumemichel View on GitHub
effort/days exp/intermediate help wanted kind/enhancement P2
Dominant language
Go
Stars
17.1k
Forks
3.2k
Avg merge
3d 18h
Merged PRs (30d)
11

Description

### Checklist

- [x] This is a bug report, not a question. Ask questions on [discuss.ipfs.tech](https://discuss.ipfs.tech/c/help/13).
- [x] I have searched on the [issue tracker](https://github.com/ipfs/kubo/issues?q=is%3Aissue) for my bug.
- [x] I am running the latest [kubo version](https://dist.ipfs.tech/#kubo) or have an issue updating.

### Installation method

dist.ipfs.tech or ipfs-update

### Version

```Text
Kubo version: 0.38.0
Repo version: 18
System version: amd64/linux
Golang version: go1.25.1
```

### Config

```json
{
"API": {
"HTTPHeaders": {}
},
"Addresses": {
"API": "/ip4/127.0.0.1/tcp/5001",
"Announce": [],
"AppendAnnounce": [],
"Gateway": "/ip4/127.0.0.1/tcp/8080",
"NoAnnounce": [],
"Swarm": [
"/ip4/0.0.0.0/tcp/4001",
"/ip6/::/tcp/4001",
"/ip4/0.0.0.0/udp/4001/webrtc-direct",
"/ip4/0.0.0.0/udp/4001/quic-v1",
"/ip4/0.0.0.0/udp/4001/quic-v1/webtransport",
"/ip6/::/udp/4001/webrtc-direct",
"/ip6/::/udp/4001/quic-v1",
"/ip6/::/udp/4001/quic-v1/webtransport"
]
},
"AutoNAT": {},
"AutoTLS": {},
"Bootstrap": [
"/ip4/104.131.131.82/tcp/4001/p2p/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ",
"/ip4/104.131.131.82/udp/4001/quic-v1/p2p/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ",
"/dnsaddr/bootstrap.libp2p.io/p2p/QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN",
"/dnsaddr/bootstrap.libp2p.io/p2p/QmQCU2EcMqAqQPR2i9bChDtGNJchTbq5TbXJJ16u19uLTa",
"/dnsaddr/bootstrap.libp2p.io/p2p/QmbLHAnMoJPWSCR5Zhtx6BHJX9KiKNN6tpvbUcqanj75Nb",
"/dnsaddr/bootstrap.libp2p.io/p2p/QmcZf59bWwK5XFi76CZX8cbJ4BhTzzA3gU1ZjYZcYW3dwt"
],
"DNS": {
"Resolvers": {}
},
"Datastore": {
"BloomFilterSize": 0,
"GCPeriod": "1h",
"HashOnRead": false,
"Spec": {
"mounts": [
{
"child": {
"path": "blocks",
"shardFunc": "/repo/flatfs/shard/v1/next-to-last/2",
"sync": true,
"type": "flatfs"
},
"mountpoint": "/blocks",
"prefix": "flatfs.datastore",
"type": "measure"
},
{
"child": {
"compression": "none",
"path": "datastore",
"type": "levelds"
},
"mountpoint": "/",
"prefix": "leveldb.datastore",
"type": "measure"
}
],
"type": "mount"
},
"StorageGCWatermark": 90,
"StorageMax": "10GB"
},
"Discovery": {
"MDNS": {
"Enabled": true
}
},
"Experimental": {
"FilestoreEnabled": false,
"Libp2pStreamMounting": false,
"OptimisticProvide": false,
"OptimisticProvideJobsPoolSize": 0,
"P2pHttpProxy": false,
"StrategicProviding": false,
"UrlstoreEnabled": false
},
"Gateway": {
"DeserializedResponses": null,
"DisableHTMLErrors": null,
"ExposeRoutingAPI": null,
"HTTPHeaders": {},
"NoDNSLink": false,
"NoFetch": false,
"PublicGateways": null,
"RootRedirect": ""
},
"Identity": {
"PeerID": "12D3KooWBJNtmfaDN1G1enLgEuWVXAHGR98fjYDH2d3wNsKqWr4s"
},
"Import": {
"CidVersion": null,
"HashFunction": null,
"UnixFSChunker": null,
"UnixFSRawLeaves": null
},
"Internal": {},
"Ipns": {
"RecordLifetime": "",
"RepublishPeriod": "24h",
"ResolveCacheSize": 128
},
"Migration": {
"DownloadSources": [],
"Keep": ""
},
"Mounts": {
"FuseAllowOther": false,
"IPFS": "/ipfs",
"IPNS": "/ipns"
},
"Peering": {
"Peers": null
},
"Pinning": {
"RemoteServices": {}
},
"Plugins": {
"Plugins": null
},
"Provider": {
"Strategy": ""
},
"Pubsub": {
"DisableSigning": false,
"Router": ""
},
"Reprovider": {},
"Routing": {
"Methods": {
"find-peers": {
"RouterName": "HttpRouterNotSupported"
},
"find-providers": {
"RouterName": "HttpRoutersParallel"
},
"get-ipns": {
"RouterName": "HttpRouterNotSupported"
},
"provide": {
"RouterName": "HttpRoutersParallel"
},
"put-ipns": {
"RouterName": "HttpRouterNotSupported"
}
},
"Routers": {
"HttpRouter1": {
"Parameters": {
"Endpoint": "http://127.0.0.1:19575"
},
"Type": "http"
},
"HttpRouter2": {
"Parameters": {
"Endpoint": "http://127.0.0.1:19576"
},
"Type": "http"
},
"HttpRouter3": {
"Parameters": {
"Endpoint": "http://127.0.0.1:19577"
},
"Type": "http"
},
"HttpRouter4": {
"Parameters": {
"Endpoint": "http://127.0.0.1:19578"
},
"Type": "http"
},
"HttpRouterNotSupported": {
"Parameters": {
"Endpoint": "http://kubohttprouternotsupported"
},
"Type": "http"
},
"HttpRoutersParallel": {
"Parameters": {
"Routers": [
{
"IgnoreErrors": true,
"RouterName": "HttpRouter1",
"Timeout": "10s"
},
{
"IgnoreErrors": true,
"RouterName": "HttpRouter2",
"Timeout": "10s"
},
{
"IgnoreErrors": true,
"RouterName": "HttpRouter3",
"Timeout": "10s"
},
{
"IgnoreErrors": true,
"RouterName": "HttpRouter4",
"Timeout": "10s"
}
]
},
"Type": "parallel"
}
},
"Type": "custom"
},
"Swarm": {
"AddrFilters": null,
"ConnMgr": {},
"DisableBandwidthMetrics": false,
"DisableNatPortMap": false,
"RelayClient": {},
"RelayService": {},
"ResourceMgr": {},
"Transports": {
"Multiplexers": {},
"Network": {},
"Security": {}
}
},
"Version": {}
}
```

### Description

# Draft GitHub Issue: Kubo 0.38 drops freshly published IPNS records with HTTP router config

## Description

While preparing a regression test for the Plebbit project I noticed that Kubo 0.38 consistently loses freshly published IPNS records whenever the node relies on custom HTTP routers and has no bootstrap peers configured. The daemon starts, the `ipfs name publish` call succeeds, but any subsequent `ipfs name resolve` hangs until the stream closes without returning the record. After restarting the daemon the behaviour is identical, so the record never reaches the local datastore.

There are no explicit errors in the daemon logs. The only symptom is that the resolve call times out (even with a 60s client-side timeout) and never yields the `/ipfs/` path that was just published. My best guess is that the HTTP router configuration—where `put-ipns`/`get-ipns` are pointed at an unsupported endpoint—causes the daemon to skip persisting the record locally, even though the publish endpoint still reports success.

## Environment

- Kubo 0.38.0 installed via `npm install kubo@0.38.0`, binary executed from `node_modules/kubo/bin/ipfs`
- Node.js 20.19.1
- Fresh repo initialised with:
- `Bootstrap = []`
- `Discovery.MDNS.Enabled = false`
- Custom routing block identical to Plebbit’s configuration (two local HTTP routers for `find-providers`/`provide`, and `get-ipns`/`put-ipns` pointed at a dummy host)
- Random high ports for API/Gateway/Swarm to avoid conflicts

## What I Was Doing

1. Initialised a new IPFS repo with the routing config above.
2. Started the daemon (`ipfs daemon`) with no bootstrap peers.
3. Added a text payload via the HTTP API (`ipfs add`).
4. Published the resulting CID with `ipfs name publish --allow-offline --resolve=false --lifetime 24h`.
5. Attempted to resolve the name immediately using `ipfs name resolve` (HTTP API, 60s timeout).
6. Stopped the daemon cleanly, restarted it, and tried resolving again.

## Expected vs Actual

- **Expected:** The resolve calls should return `/ipfs/` immediately and after restart.
- **Actual:** Both resolves time out without yielding any value. Even after waiting the full 60s, the stream closes with no entries returned.

## Steps To Reproduce

All of the above is automated in this repository:

```bash
git clone https://github.com/Rinse12/reproduce_kubo_not_storing_ipns_record
npm install
npm run reproduce
```

Sample run (trimmed for brevity):

```
------------------------------
-- Using packaged Kubo 0.38.0 --
------------------------------
Binary path: .../node_modules/kubo/bin/ipfs
Selected ports: { api: 41047, gateway: 40758, swarmTcp: 42351, swarmQuic: 56172 }
...
Added CID: QmfNCoN51J2fLkbSTTFTBbYFX23GEqAhLF5DLjDSjXNf5h
Published IPNS: {
name: 'k51qzi5uqu5dlws3n28q0wq2xf5vzbadu84buuqz5h5kma6mpmnwgqc38uangp',
value: '/ipfs/QmfNCoN51J2fLkbSTTFTBbYFX23GEqAhLF5DLjDSjXNf5h'
}
Resolving IPNS name ... with options { timeout: 60000 }
Immediate resolve failed: Error: No IPNS result returned before the stream closed
...
Post-restart resolve failed as expected: No IPNS result returned before the stream closed
```

Every run so far ends the same way: the publish reports success, but neither the immediate nor post-restart resolve ever returns the new record.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.