ipfs/kubo · warning
querying datastore for stale DHT value records: %w
Error message
querying datastore for stale DHT value records: %w
What it means
Raised by deleteStaleDHTValueRecords in the one-time migration that purges pre-v0.42.0 format DHT value records from the datastore. When the initial keys-only datastore Query fails to start, the error is wrapped with this message. purgeStaleDHTValueRecords logs it and defers the purge to the next daemon start; it is non-fatal to node operation.
Source
Thrown at core/node/storage.go:208
logger.Warnw("writing DHT value purge marker failed", "error", err)
return
}
if err := ds.Sync(ctx, dhtValuePurgeDoneKey); err != nil {
logger.Warnw("syncing DHT value purge marker failed", "error", err)
return
}
if count > 0 {
logger.Infow("purged stale DHT value records from datastore", "keys", count)
}
}
// deleteStaleDHTValueRecords scans the whole datastore (keys only) and
// deletes old-format DHT value records in batches. It returns the number of
// deleted keys.
func deleteStaleDHTValueRecords(ctx context.Context, ds datastore.Batching) (int, error) {
results, err := ds.Query(ctx, query.Query{Prefix: "/", KeysOnly: true})
if err != nil {
return 0, fmt.Errorf("querying datastore for stale DHT value records: %w", err)
}
defer results.Close()
var batch datastore.Batch
var count, pending int
for result := range results.Next() {
if ctx.Err() != nil {
return count, ctx.Err()
}
if result.Error != nil {
return count, fmt.Errorf("iterating datastore keys: %w", result.Error)
}
if !isStaleDHTValueRecordKey(result.Key) {
continue
}
if batch == nil {
batch, err = ds.Batch(ctx)
if err != nil {View on GitHub (pinned to 329838acdf)
Solutions
- Read the wrapped error in the warning log line 'purge of stale DHT value records failed'
- Check the repo lock isn't held by another ipfs process (pkill stale daemons)
- Run datastore integrity/repair tools and check disk health
- Restart the daemon — the purge retries automatically on next start
Defensive patterns
Strategy: retry
Validate before calling
// verify datastore opens and queries before migration
results, err := ds.Query(ctx, query.Query{Prefix: "/", KeysOnly: true})
if err != nil {
log.Warnf("datastore unusable, purge deferred: %v", err)
} Try / catch
_, err := deleteStaleDHTValueRecords(ctx, ds)
if err != nil && !errors.Is(err, context.Canceled) {
log.Warnw("purge failed, will retry on next start", "error", err)
} Prevention
- Ensure only one ipfs process uses the repo at a time
- Check disk health and datastore integrity after crashes
- Let the startup migration finish before shutting down
When it happens
Trigger: Daemon start runs the stale-record purge; ds.Query(ctx, query.Query{Prefix:"/", KeysOnly:true}) fails immediately — datastore is locked, corrupted, or cannot open iterators.
Common situations: Corrupted badger/levelds datastore after crash, another process holding the repo lock, disk I/O errors, or read-only filesystem.
Related errors
- iterating datastore keys: %w
- creating delete batch: %w
- batch deleting stale key %s: %w
- committing delete batch: %w
- The Experimental.AcceleratedDHTClient key has been moved to
AI-assisted analysis of ipfs/kubo@329838acdf (2026-09-03).
Data as JSON: /api/errors/ee312be4912cc29e.
Report an issue: GitHub.