ipfs/kubo · error
cannot add named links to a UnixFS %s node, only Directory n
Error message
cannot add named links to a UnixFS %s node, only Directory nodes support link addition at the dag-pb level (see https://specs.ipfs.tech/unixfs/)
What it means
AddLink at the dag-pb level only supports plain UnixFS Directory nodes. Other UnixFS node types (File, Raw, Symlink, Metadata...) have no meaningful 'named links' semantics for link addition and dagutils.Editor cannot keep their metadata consistent. The error reports the actual node type so the caller knows what they passed.
Source
Thrown at core/coreapi/object.go:83
// https://specs.ipfs.tech/unixfs/#pbnode-links-name
// https://github.com/ipfs/kubo/issues/7190
if !options.SkipUnixFSValidation {
fsNode, err := ft.FSNodeFromBytes(basePb.Data())
if err != nil {
return path.ImmutablePath{}, fmt.Errorf(
"cannot add named links to 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 add links to a HAMTShard at the dag-pb level " +
"(would corrupt the HAMT bitfield); use 'ipfs files' " +
"commands instead, or pass --allow-non-unixfs to override")
default:
return path.ImmutablePath{}, fmt.Errorf(
"cannot add named links to a UnixFS %s node, "+
"only Directory nodes support link addition at the dag-pb level "+
"(see https://specs.ipfs.tech/unixfs/)",
fsNode.Type())
}
}
var createfunc func() *dag.ProtoNode
if options.Create {
createfunc = ft.EmptyDirNode
}
e := dagutils.NewDagEditor(basePb, api.dag)
err = e.InsertNodeAtPath(ctx, name, childNd, createfunc)
if err != nil {
return path.ImmutablePath{}, err
}View on GitHub (pinned to 329838acdf)
Solutions
- Pass the directory CID/path, not a file or other node
- Use 'ipfs files' / MFS API for modifying UnixFS content
- Use --allow-non-unixfs to bypass validation if you explicitly want raw dag-pb editing
Example fix
// before ipfs object patch add-link QmFileCid name.txt QmChild // after: resolve to the directory first ipfs object patch add-link QmDirCid name.txt QmChild
Defensive patterns
Strategy: validation
Validate before calling
fsNode, err := ft.FSNodeFromBytes(pbNode.Data())
if err != nil || fsNode.Type() != ft.TDirectory {
// not a plain directory: refuse dag-pb link addition
} 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
- Always pass directory paths, never file paths, to AddLink
- Resolve paths with type checks before patch operations
- Prefer MFS API for all UnixFS content edits
When it happens
Trigger: AddLink on a resolved path whose root dag-pb node is a UnixFS node of any type other than TDirectory or THAMTShard (e.g. a file or raw leaf).
Common situations: Passing a file CID instead of a directory CID to object patch add-link; path resolution landing on an inner file node due to a typo'd path.
Related errors
- cannot remove links from a UnixFS %s node, only Directory no
- 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/29aebac726f6a69a.
Report an issue: GitHub.