{"record":{"id":"9681cc61a64ab8bc","repo":"ipfs/kubo","slug":"committing-delete-batch-w","errorCode":null,"errorMessage":"committing delete batch: %w","messagePattern":"committing delete batch: %w","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"core/node/storage.go","lineNumber":237,"sourceCode":"\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 {\n\t\t\t\treturn count, fmt.Errorf(\"creating delete batch: %w\", err)\n\t\t\t}\n\t\t}\n\t\tif err := batch.Delete(ctx, datastore.NewKey(result.Key)); err != nil {\n\t\t\treturn count, fmt.Errorf(\"batch deleting stale key %s: %w\", result.Key, err)\n\t\t}\n\t\tcount++\n\t\tpending++\n\t\tif pending >= purgeBatchSize {\n\t\t\tif err := batch.Commit(ctx); err != nil {\n\t\t\t\treturn count, fmt.Errorf(\"committing delete batch: %w\", err)\n\t\t\t}\n\t\t\tbatch = nil\n\t\t\tpending = 0\n\t\t}\n\t}\n\tif pending > 0 {\n\t\tif err := batch.Commit(ctx); err != nil {\n\t\t\treturn count, fmt.Errorf(\"committing delete batch: %w\", err)\n\t\t}\n\t}\n\tif count > 0 {\n\t\tif err := ds.Sync(ctx, datastore.NewKey(\"/\")); err != nil {\n\t\t\treturn count, fmt.Errorf(\"syncing deletes: %w\", err)\n\t\t}\n\t}\n\treturn count, nil\n}\n","sourceCodeStart":219,"sourceCodeEnd":255,"githubUrl":"https://github.com/ipfs/kubo/blob/329838acdfafae224582930457efe80aa217afc0/core/node/storage.go#L219-L255","documentation":"Raised by deleteStaleDHTValueRecords when batch.Commit(ctx) fails after accumulating purgeBatchSize deletes (or the trailing partial batch). The deletes are not durably applied; the count of attempted deletions is returned and the whole purge is retried on the next daemon start. purgeStaleDHTValueRecords logs it as a warning, not a fatal error.","triggerScenarios":"Every purgeBatchSize (batch-sized) commits of stale-key deletions fail — datastore commit/write error: disk full, I/O failure, transaction size limits in the backend, or context cancellation.","commonSituations":"Disk exhaustion on busy nodes, badger transaction too large / write stalls, levelds I/O errors, or the operator stopping the daemon during startup migration.","solutions":["Check disk space and I/O health; the wrapped error names the datastore cause","Restart the daemon and let the migration complete uninterrupted","If a backend rejects large transactions, the periodic batching in this code already limits size — verify no custom datastore wrapper interferes","Restore from backup if the datastore is consistently failing to commit"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// preflight: confirm the datastore can commit a trivial batch\nb, err := ds.Batch(ctx)\nif err == nil {\n    _ = b.Put(ctx, datastore.NewKey(\"/health/probe\"), []byte{1})\n    err = b.Commit(ctx)\n}\nif err != nil {\n    log.Warnf(\"datastore commits failing: %v\", err)\n}","typeGuard":null,"tryCatchPattern":"count, err := deleteStaleDHTValueRecords(ctx, ds)\nif err != nil && strings.Contains(err.Error(), \"committing delete batch\") {\n    log.Warnw(\"batch commit failed, purge will retry next start\", \"deletedSoFar\", count)\n}","preventionTips":["Monitor disk space and datastore write latency","Avoid custom datastore wrappers that break batch semantics","Let the one-time migration complete before daemon shutdown"],"tags":["datastore","batch","commit","migration","dht"],"backgroundTag":"datastore-commit-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"}