ipfs/kubo · error
cannot remove links from a UnixFS %s node, only Directory no
Error message
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/)
What it means
RmLink only supports plain UnixFS Directory nodes at the dag-pb level; any other UnixFS type (file, raw, symlink, etc.) cannot have named links removed meaningfully. The message includes the offending node type and links the UnixFS spec.
Source
Thrown at core/coreapi/object.go:151
// 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
}
nnode, err := e.Finalize(ctx, api.dag)
if err != nil {
return path.ImmutablePath{}, err
}View on GitHub (pinned to 329838acdf)
Solutions
- Target a plain UnixFS directory path/CID
- Use 'ipfs files rm' / MFS API for content operations
- Use --allow-non-unixfs to force raw dag-pb removal
Example fix
// before ipfs object patch rm-link QmFileCid link // after ipfs object patch rm-link QmDirCid link
Defensive patterns
Strategy: validation
Validate before calling
fsNode, err := ft.FSNodeFromBytes(pbNode.Data())
if err != nil || fsNode.Type() != ft.TDirectory {
// only plain directories support dag-pb link removal
} Type guard
func isPlainUnixFSDirectory(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.TDirectory
} Prevention
- Resolve and type-check the target before RmLink
- Use 'ipfs files rm' for files and other UnixFS types
- Restrict object patch usage to plain directories in scripts
When it happens
Trigger: RmLink on a resolved node whose fsNode.Type() is neither TDirectory nor THAMTShard.
Common situations: Typo in path resolves to a file node instead of the directory; attempting link removal on a UnixFS file's internal data node.
Related errors
- cannot add named links to a UnixFS %s node, only Directory n
- cannot add links to a HAMTShard at the dag-pb level (would c
- cannot remove links from a non-UnixFS dag-pb node; pass --al
- cannot remove links from a HAMTShard at the dag-pb level (wo
- unexpected Objects len
AI-assisted analysis of ipfs/kubo@329838acdf (2026-09-03).
Data as JSON: /api/errors/e46c0322905d676d.
Report an issue: GitHub.