{"record":{"id":"90473690210f8e2b","repo":"ipfs/kubo","slug":"cannot-add-named-links-to-a-non-unixfs-dag-pb-node","errorCode":null,"errorMessage":"cannot add named links to a non-UnixFS dag-pb node; pass --allow-non-unixfs to skip validation","messagePattern":"cannot add named links to a non-UnixFS dag-pb node; pass --allow-non-unixfs to skip validation","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/coreapi/object.go","lineNumber":70,"sourceCode":"\t\treturn path.ImmutablePath{}, err\n\t}\n\n\tbasePb, ok := baseNd.(*dag.ProtoNode)\n\tif !ok {\n\t\treturn path.ImmutablePath{}, dag.ErrNotProtobuf\n\t}\n\n\t// This command operates at the dag-pb level via dagutils.Editor, which\n\t// only manipulates ProtoNode links without updating UnixFS metadata.\n\t// Only plain UnixFS Directory nodes are safe to mutate this way.\n\t// File nodes: adding links corrupts Blocksizes, content lost on read-back.\n\t// HAMTShard nodes: bitfield not updated, shard trie becomes inconsistent.\n\t// https://specs.ipfs.tech/unixfs/#pbnode-links-name\n\t// https://github.com/ipfs/kubo/issues/7190\n\tif !options.SkipUnixFSValidation {\n\t\tfsNode, err := ft.FSNodeFromBytes(basePb.Data())\n\t\tif err != nil {\n\t\t\treturn path.ImmutablePath{}, fmt.Errorf(\n\t\t\t\t\"cannot add named links to a non-UnixFS dag-pb node; \" +\n\t\t\t\t\t\"pass --allow-non-unixfs to skip validation\")\n\t\t}\n\t\tswitch fsNode.Type() {\n\t\tcase ft.TDirectory:\n\t\t\t// plain directories: safe, no link-count metadata to desync\n\t\tcase ft.THAMTShard:\n\t\t\treturn path.ImmutablePath{}, fmt.Errorf(\n\t\t\t\t\"cannot add links to a HAMTShard at the dag-pb level \" +\n\t\t\t\t\t\"(would corrupt the HAMT bitfield); use 'ipfs files' \" +\n\t\t\t\t\t\"commands instead, or pass --allow-non-unixfs to override\")\n\t\tdefault:\n\t\t\treturn path.ImmutablePath{}, fmt.Errorf(\n\t\t\t\t\"cannot add named links to a UnixFS %s node, \"+\n\t\t\t\t\t\"only Directory nodes support link addition at the dag-pb level \"+\n\t\t\t\t\t\"(see https://specs.ipfs.tech/unixfs/)\",\n\t\t\t\tfsNode.Type())\n\t\t}","sourceCodeStart":52,"sourceCodeEnd":88,"githubUrl":"https://github.com/ipfs/kubo/blob/329838acdfafae224582930457efe80aa217afc0/core/coreapi/object.go#L52-L88","documentation":"ObjectAPI.AddLink links by name into a dag-pb node, but named links are only safe on UnixFS nodes (directory/hash metadata must stay consistent). When the target node's data cannot be parsed as a UnixFS node, the API refuses to edit it and suggests the --allow-non-unixfs escape hatch, which skips validation (with known HAMT-shard consistency risks, see issue 7190).","triggerScenarios":"Calling AddLink on a dag-pb node whose Data field is not valid UnixFS protobuf (raw dag-pb node, custom data, or empty), with SkipUnixFSValidation=false (the default).","commonSituations":"Manually crafted dag-pb nodes added via the DAG API, then edited with `ipfs object patch <cid> add-link`; HAMT-shard directories with deserialized data; nodes created by other tools with non-UnixFS Data.","solutions":["Verify the target CID is a UnixFS directory (created via `ipfs add` or MFS), not a raw dag-pb node.","Inspect with `ipfs dag get <cid>` or `ipfs files stat` to confirm the node type.","If you explicitly need to edit a non-UnixFS dag-pb node, pass --allow-non-unixfs (SkipUnixFSValidation=true) and accept the consistency risk.","Use MFS (`ipfs files`) to build/edit directory structures instead of raw object patching."],"exampleFix":"// before\nipfs object patch <raw-dagpb-cid> add-link name <target>  # fails\n// after\n# only if you know the node is not UnixFS:\nipfs object patch --allow-non-unixfs <cid> add-link name <target>","handlingStrategy":"validation","validationCode":"node, err := api.Dag().Get(ctx, path.New(targetCid))\nif err != nil {\n    return err\n}\npb, ok := node.(ipldprime.Node) // inspect Data via dag-pb codec\n// confirm the node is a UnixFS directory before AddLink; otherwise use MFS","typeGuard":null,"tryCatchPattern":"ip, err := api.Object().AddLink(ctx, base, name, child, opts)\nif err != nil && strings.Contains(err.Error(), \"non-UnixFS dag-pb\") {\n    // rebuild the directory with MFS or retry with --allow-non-unixfs\n}","preventionTips":["Build and edit directories via MFS rather than raw object patching.","Only AddLink onto nodes produced by `ipfs add` (UnixFS).","Inspect node type with `ipfs dag get` before patching.","Reserve SkipUnixFSValidation for deliberately non-UnixFS workflows."],"tags":["dag-pb","unixfs","validation","object-api"],"backgroundTag":"non-unixfs-dag-pb-node","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"}