ipfs/kubo · error

pin check failed: %w

Error message

pin check failed: %w

What it means

FilterPinned checks each CID against the pinset before block removal. If the pinner itself fails (e.g. the underlying blockstore/datastore read of pin metadata errors), it emits a RemovedBlock whose Error wraps that failure with 'pin check failed' on the output channel and aborts filtering (returns nil). The removal operation typically surfaces this as a per-block error rather than a returned error.

Source

Thrown at blocks/blockstoreutil/remove.go:82

				out <- &RemovedBlock{Hash: c.String(), Error: err}
			} else if !opts.Quiet {
				out <- &RemovedBlock{Hash: c.String()}
			}
		}
	}()
	return out, nil
}

// FilterPinned takes a slice of Cids and returns it with the pinned Cids
// removed. If a Cid is pinned, it will place RemovedBlock objects in the given
// out channel, with an error which indicates that the Cid is pinned.
// This function is used in RmBlocks to filter out any blocks which are not
// to be removed (because they are pinned).
func FilterPinned(ctx context.Context, pins pin.Pinner, out chan<- any, cids []cid.Cid) []cid.Cid {
	stillOkay := make([]cid.Cid, 0, len(cids))
	res, err := pins.CheckIfPinned(ctx, cids...)
	if err != nil {
		out <- &RemovedBlock{Error: fmt.Errorf("pin check failed: %w", err)}
		return nil
	}
	for _, r := range res {
		if !r.Pinned() {
			stillOkay = append(stillOkay, r.Key)
		} else {
			out <- &RemovedBlock{
				Hash:  r.Key.String(),
				Error: errors.New(r.String()),
			}
		}
	}
	return stillOkay
}

View on GitHub (pinned to 329838acdf)

Solutions

  1. Run `ipfs repo fsck` / `ipfs pin ls` to verify pin metadata integrity, then retry the removal
  2. Check datastore health (disk space, permissions) and repair or restore the repo datastore
  3. Stop concurrent pin/gc operations that may race, then retry
  4. Inspect the wrapped inner error (the %w chain) with errors.Is/As to identify the datastore-level cause
Defensive patterns

Strategy: try-catch

Validate before calling

// pre-check pins before removal
res, err := pins.CheckIfPinned(ctx, cids...)
if err != nil { return fmt.Errorf("pinset unreadable: %w", err) }

Try / catch

cids, errCh := blockstoreutil.FilterPinned(ctx, pins, out, cids)
for rb := range out {
    if b, ok := rb.(*blockstoreutil.RemovedBlock); ok && b.Error != nil {
        if strings.HasPrefix(b.Error.Error(), "pin check failed") {
            // datastore/pin metadata failure: fsck repo, retry
        }
    }
}

Prevention

When it happens

Trigger: Calling RmBlocks/FilterPinned when pins.CheckIfPinned returns an error — corrupted pin metadata in the datastore, direct/pin-mode datastore failures, or passing a closed/invalid pinset. Also triggered when the caller's `out` channel consumer cannot keep up (blocks removal mid-check).

Common situations: 'ipfs pin ls' or 'ipfs repo gc' after a datastore corruption; disk full or levelds/badger I/O errors while reading pin records; concurrent 'ipfs pin rm' racing with 'ipfs repo gc'; running repo operations on a repo from an incompatible newer version.

Related errors


AI-assisted analysis of ipfs/kubo@329838acdf (2026-09-03). Data as JSON: /api/errors/ea8e02bb1f44a933. Report an issue: GitHub.