ipfs/kubo · error
querying orphaned keystore data: %w
Error message
querying orphaned keystore data: %w
What it means
purgeOrphanedKeystoreData runs a keys-only Query over the datastore with the orphaned-prefix to find keystore entries that no longer belong to any mounted keystore, then batches deletes for them. This error wraps a failure returned by ds.Query itself, meaning the sweep never started — the underlying datastore refused or failed the query. The deferred results.Close() and iteration never happen, so no data was deleted.
Source
Thrown at core/node/provider.go:552
const purgeBatchSize = 1 << 12 // 4096
// purgeOrphanedKeystoreData deletes all keys under /provider/keystore/ from the
// shared repo datastore. These were written by older Kubo versions that stored
// provider keystore data inline in the shared datastore. The new code uses
// separate filesystem datastores under <repo>/{KeystoreDatastorePath}/ instead.
//
// The operation is idempotent and safe to interrupt: partial completion is
// fine because already-deleted keys are no-ops on re-run.
func purgeOrphanedKeystoreData(ctx context.Context, ds datastore.Batching) error {
orphanedPrefix := providerDatastoreKey.Child(keystoreDatastoreKey).String()
syncKey := datastore.NewKey(orphanedPrefix)
results, err := ds.Query(ctx, query.Query{
Prefix: orphanedPrefix,
KeysOnly: true,
})
if err != nil {
return fmt.Errorf("querying orphaned keystore data: %w", err)
}
defer results.Close()
var batch datastore.Batch
var count, pending int
for result := range results.Next() {
if ctx.Err() != nil {
return ctx.Err()
}
if result.Error != nil {
return fmt.Errorf("iterating orphaned keystore data: %w", result.Error)
}
if batch == nil {
batch, err = ds.Batch(ctx)
if err != nil {
return fmt.Errorf("creating batch for orphaned keystore cleanup: %w", err)
}
}View on GitHub (pinned to 329838acdf)
Solutions
- Inspect the wrapped cause at the end of the chain — it identifies which datastore and why (I/O error, not open, etc.).
- Check permissions and disk space/free inodes on the repo directory containing the keystore datastores.
- Stop the node, run datastore integrity checks (e.g. flatfs verify, leveldb recovery), and restart.
- If the keystore datastore directory was deleted externally, restore it from backup or re-create it via MountKeystoreDatastores.
- Retry the purge after fixing the underlying datastore; the error is pre-delete, so it is safe to rerun.
Example fix
// before (purge on possibly-closed datastore)
results, err := ds.Query(ctx, query.Query{Prefix: orphanedPrefix, KeysOnly: true})
if err != nil {
return fmt.Errorf("querying orphaned keystore data: %w", err)
}
// after (caller-side guard)
if err := pingDatastore(ctx, ds); err != nil { // health check before purge
return fmt.Errorf("skipping orphan purge, datastore unhealthy: %w", err)
}
results, err := ds.Query(ctx, query.Query{Prefix: orphanedPrefix, KeysOnly: true})
if err != nil {
return fmt.Errorf("querying orphaned keystore data: %w", err)
} Defensive patterns
Strategy: retry
Validate before calling
// Before the purge, confirm the datastore answers a trivial query:
probe, err := ds.Query(ctx, query.Query{Prefix: orphanedPrefix, KeysOnly: true, Limit: 1})
if err != nil {
return fmt.Errorf("datastore unhealthy, aborting purge: %w", err)
}
probe.Close() Try / catch
results, err := ds.Query(ctx, query.Query{Prefix: orphanedPrefix, KeysOnly: true})
if err != nil {
if ctx.Err() != nil {
return fmt.Errorf("purge canceled: %w", ctx.Err())
}
// transient I/O problems justify one bounded retry; nothing was deleted
return retryPurge(ctx, ds, 1)
} Prevention
- Monitor free disk space and filesystem health on the repo volume
- Run maintenance/purge tasks only while the node owns the repo lock
- Back up the keystore datastore directories before purge operations
- After unclean shutdowns, run datastore verify/repair before sweeping
When it happens
Trigger: Calling purgeOrphanedKeystoreData when ds.Query(ctx, query.Query{Prefix: orphanedPrefix, KeysOnly: true}) errors — e.g. the mounted datastore is closed/unavailable, the underlying flatfs/levelds directory is unreadable or corrupted, or the query was rejected by a datastore that does not support prefix queries in its current state.
Common situations: Disk I/O errors or a full disk under the repo directory; keystore datastore directory deleted or permission-changed while the node runs; running the purge against a datastore implementation with query limitations; corrupted keystore database after an unclean shutdown.
Related errors
- unexpected keystore suffix %q, expected "0" or "1"
- creating datastore config for %s: %w
- iterating orphaned keystore data: %w
- 'type' field missing or not a string
- unknown datastore type: %s
AI-assisted analysis of ipfs/kubo@329838acdf (2026-09-03).
Data as JSON: /api/errors/850406b5a645ff6f.
Report an issue: GitHub.