{"record":{"id":"ee312be4912cc29e","repo":"ipfs/kubo","slug":"querying-datastore-for-stale-dht-value-records-w","errorCode":null,"errorMessage":"querying datastore for stale DHT value records: %w","messagePattern":"querying datastore for stale DHT value records: %w","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"core/node/storage.go","lineNumber":208,"sourceCode":"\t\tlogger.Warnw(\"writing DHT value purge marker failed\", \"error\", err)\n\t\treturn\n\t}\n\tif err := ds.Sync(ctx, dhtValuePurgeDoneKey); err != nil {\n\t\tlogger.Warnw(\"syncing DHT value purge marker failed\", \"error\", err)\n\t\treturn\n\t}\n\tif count > 0 {\n\t\tlogger.Infow(\"purged stale DHT value records from datastore\", \"keys\", count)\n\t}\n}\n\n// deleteStaleDHTValueRecords scans the whole datastore (keys only) and\n// deletes old-format DHT value records in batches. It returns the number of\n// deleted keys.\nfunc deleteStaleDHTValueRecords(ctx context.Context, ds datastore.Batching) (int, error) {\n\tresults, err := ds.Query(ctx, query.Query{Prefix: \"/\", KeysOnly: true})\n\tif err != nil {\n\t\treturn 0, fmt.Errorf(\"querying datastore for stale DHT value records: %w\", err)\n\t}\n\tdefer results.Close()\n\n\tvar batch datastore.Batch\n\tvar count, pending int\n\tfor result := range results.Next() {\n\t\tif ctx.Err() != nil {\n\t\t\treturn count, ctx.Err()\n\t\t}\n\t\tif result.Error != nil {\n\t\t\treturn count, fmt.Errorf(\"iterating datastore keys: %w\", result.Error)\n\t\t}\n\t\tif !isStaleDHTValueRecordKey(result.Key) {\n\t\t\tcontinue\n\t\t}\n\t\tif batch == nil {\n\t\t\tbatch, err = ds.Batch(ctx)\n\t\t\tif err != nil {","sourceCodeStart":190,"sourceCodeEnd":226,"githubUrl":"https://github.com/ipfs/kubo/blob/329838acdfafae224582930457efe80aa217afc0/core/node/storage.go#L190-L226","documentation":"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.","triggerScenarios":"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.","commonSituations":"Corrupted badger/levelds datastore after crash, another process holding the repo lock, disk I/O errors, or read-only filesystem.","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"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// verify datastore opens and queries before migration\nresults, err := ds.Query(ctx, query.Query{Prefix: \"/\", KeysOnly: true})\nif err != nil {\n    log.Warnf(\"datastore unusable, purge deferred: %v\", err)\n}","typeGuard":null,"tryCatchPattern":"_, err := deleteStaleDHTValueRecords(ctx, ds)\nif err != nil && !errors.Is(err, context.Canceled) {\n    log.Warnw(\"purge failed, will retry on next start\", \"error\", err)\n}","preventionTips":["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"],"tags":["datastore","migration","dht","purge"],"backgroundTag":"datastore-query-failed","analyzedSha":"329838acdfafae224582930457efe80aa217afc0","analyzedAt":"2026-09-03T18:30:52.135Z","contentChangedAt":"2026-09-03T18:30:52.135Z","schemaVersion":2},"datasetVersion":"2026-09-11T00:17:11.886Z"}