{"record":{"id":"ea8e02bb1f44a933","repo":"ipfs/kubo","slug":"pin-check-failed-w","errorCode":null,"errorMessage":"pin check failed: %w","messagePattern":"pin check failed: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"blocks/blockstoreutil/remove.go","lineNumber":82,"sourceCode":"\t\t\t\tout <- &RemovedBlock{Hash: c.String(), Error: err}\n\t\t\t} else if !opts.Quiet {\n\t\t\t\tout <- &RemovedBlock{Hash: c.String()}\n\t\t\t}\n\t\t}\n\t}()\n\treturn out, nil\n}\n\n// FilterPinned takes a slice of Cids and returns it with the pinned Cids\n// removed. If a Cid is pinned, it will place RemovedBlock objects in the given\n// out channel, with an error which indicates that the Cid is pinned.\n// This function is used in RmBlocks to filter out any blocks which are not\n// to be removed (because they are pinned).\nfunc FilterPinned(ctx context.Context, pins pin.Pinner, out chan<- any, cids []cid.Cid) []cid.Cid {\n\tstillOkay := make([]cid.Cid, 0, len(cids))\n\tres, err := pins.CheckIfPinned(ctx, cids...)\n\tif err != nil {\n\t\tout <- &RemovedBlock{Error: fmt.Errorf(\"pin check failed: %w\", err)}\n\t\treturn nil\n\t}\n\tfor _, r := range res {\n\t\tif !r.Pinned() {\n\t\t\tstillOkay = append(stillOkay, r.Key)\n\t\t} else {\n\t\t\tout <- &RemovedBlock{\n\t\t\t\tHash:  r.Key.String(),\n\t\t\t\tError: errors.New(r.String()),\n\t\t\t}\n\t\t}\n\t}\n\treturn stillOkay\n}\n","sourceCodeStart":64,"sourceCodeEnd":97,"githubUrl":"https://github.com/ipfs/kubo/blob/329838acdfafae224582930457efe80aa217afc0/blocks/blockstoreutil/remove.go#L64-L97","documentation":"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.","triggerScenarios":"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).","commonSituations":"'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.","solutions":["Run `ipfs repo fsck` / `ipfs pin ls` to verify pin metadata integrity, then retry the removal","Check datastore health (disk space, permissions) and repair or restore the repo datastore","Stop concurrent pin/gc operations that may race, then retry","Inspect the wrapped inner error (the %w chain) with errors.Is/As to identify the datastore-level cause"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// pre-check pins before removal\nres, err := pins.CheckIfPinned(ctx, cids...)\nif err != nil { return fmt.Errorf(\"pinset unreadable: %w\", err) }","typeGuard":null,"tryCatchPattern":"cids, errCh := blockstoreutil.FilterPinned(ctx, pins, out, cids)\nfor rb := range out {\n    if b, ok := rb.(*blockstoreutil.RemovedBlock); ok && b.Error != nil {\n        if strings.HasPrefix(b.Error.Error(), \"pin check failed\") {\n            // datastore/pin metadata failure: fsck repo, retry\n        }\n    }\n}","preventionTips":["Run `ipfs repo fsck` when pin metadata is suspected corrupt","Avoid racing `pin rm`/`pin add` with `repo gc`/`block rm`","Monitor disk space and datastore health"],"tags":["go","ipfs","pins","blockstore","gc"],"backgroundTag":"pin-check-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"}