ipfs/kubo · error
cannot remove links from a HAMTShard at the dag-pb level (wo
Error message
cannot remove links from a HAMTShard at the dag-pb level (would corrupt the HAMT bitfield); use 'ipfs files rm' instead, or pass --allow-non-unixfs to override
What it means
Mirror of the AddLink HAMTShard case for removal: deleting a link from a HAMTShard via dag-pb editing would leave the HAMT bitfield and bucket structure inconsistent, breaking future lookups. RmLink refuses and directs to 'ipfs files rm' or the explicit override.
Source
Thrown at core/coreapi/object.go:146
basePb, ok := baseNd.(*dag.ProtoNode)
if !ok {
return path.ImmutablePath{}, dag.ErrNotProtobuf
}
// Same validation as AddLink: dagutils.Editor operates at the dag-pb
// level and cannot update UnixFS metadata (HAMT bitfields, Blocksizes).
if !options.SkipUnixFSValidation {
fsNode, err := ft.FSNodeFromBytes(basePb.Data())
if err != nil {
return path.ImmutablePath{}, fmt.Errorf(
"cannot remove links from a non-UnixFS dag-pb node; " +
"pass --allow-non-unixfs to skip validation")
}
switch fsNode.Type() {
case ft.TDirectory:
// plain directories: safe, no link-count metadata to desync
case ft.THAMTShard:
return path.ImmutablePath{}, fmt.Errorf(
"cannot remove links from a HAMTShard at the dag-pb level " +
"(would corrupt the HAMT bitfield); use 'ipfs files rm' " +
"instead, or pass --allow-non-unixfs to override")
default:
return path.ImmutablePath{}, fmt.Errorf(
"cannot remove links from a UnixFS %s node, "+
"only Directory nodes support link removal at the dag-pb level "+
"(see https://specs.ipfs.tech/unixfs/)",
fsNode.Type())
}
}
e := dagutils.NewDagEditor(basePb, api.dag)
err = e.RmLink(ctx, link)
if err != nil {
return path.ImmutablePath{}, err
}View on GitHub (pinned to 329838acdf)
Solutions
- Use MFS API or 'ipfs files rm /path/in/sharded-dir'
- Convert the directory back to a plain directory if legacy patching is required
- Pass --allow-non-unixfs only with full awareness of bitfield corruption
Example fix
// before ipfs object patch rm-link <hamt-dir-cid> child.txt // after ipfs files rm /my-hamt-dir/child.txt
Defensive patterns
Strategy: validation
Validate before calling
fsNode, err := ft.FSNodeFromBytes(pbNode.Data())
if err == nil && fsNode.Type() == ft.THAMTShard {
// use 'ipfs files rm' / MFS instead of RmLink
} Type guard
func isHAMTShard(n ipld.Node) bool {
pb, ok := n.(*dagpb.PBNode)
if !ok { return false }
fsn, err := ft.FSNodeFromBytes(pb.Data())
return err == nil && fsn.Type() == ft.THAMTShard
} Prevention
- Never use object patch rm-link on sharded directories
- Use MFS operations which handle HAMT re-sharding correctly
- Detect sharding early with 'ipfs files stat' (is-sharded)
When it happens
Trigger: RmLink on a path resolving to a UnixFS HAMTShard root with SkipUnixFSValidation=false.
Common situations: Scripts removing entries from sharded MFS root directories via the old object patch rm-link RPC after the directory was converted to a HAMT shard.
Related errors
- cannot add links to a HAMTShard at the dag-pb level (would c
- cannot add named links to a UnixFS %s node, only Directory n
- cannot remove links from a non-UnixFS dag-pb node; pass --al
- cannot remove links from a UnixFS %s node, only Directory no
- unexpected Objects len
AI-assisted analysis of ipfs/kubo@329838acdf (2026-09-03).
Data as JSON: /api/errors/119daebe7b351430.
Report an issue: GitHub.