{"record":{"id":"8cc099dc57ceaa4f","repo":"ipfs/kubo","slug":"cannot-remove-links-from-a-non-unixfs-dag-pb-node","errorCode":null,"errorMessage":"cannot remove links from a non-UnixFS dag-pb node; pass --allow-non-unixfs to skip validation","messagePattern":"cannot remove links from 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":138,"sourceCode":"\t\treturn path.ImmutablePath{}, err\n\t}\n\n\tbaseNd, err := api.core().ResolveNode(ctx, base)\n\tif err != nil {\n\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// Same validation as AddLink: dagutils.Editor operates at the dag-pb\n\t// level and cannot update UnixFS metadata (HAMT bitfields, Blocksizes).\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 remove links from 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 remove links from a HAMTShard at the dag-pb level \" +\n\t\t\t\t\t\"(would corrupt the HAMT bitfield); use 'ipfs files rm' \" +\n\t\t\t\t\t\"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 remove links from a UnixFS %s node, \"+\n\t\t\t\t\t\"only Directory nodes support link removal 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":120,"sourceCodeEnd":156,"githubUrl":"https://github.com/ipfs/kubo/blob/329838acdfafae224582930457efe80aa217afc0/core/coreapi/object.go#L120-L156","documentation":"RmLink uses dagutils.Editor which operates purely at the dag-pb level; if the node's data is not valid UnixFS at all, the library cannot verify that removing a link keeps metadata consistent, so it refuses. FSNodeFromBytes failed on basePb.Data(), meaning the node is a plain dag-pb node (e.g. created by 'ipfs dag put') not wrapped in UnixFS. --allow-non-unixfs skips this check.","triggerScenarios":"Calling RmLink (object patch rm-link) with SkipUnixFSValidation=false on a node whose protobuf data does not decode to a valid UnixFS FSNode (dag-put-created IPLD nodes, raw dag-pb).","commonSituations":"Using legacy object patch commands on nodes built with modern 'ipfs dag put' or imported raw dag-pb data; scripts written pre-UnixFS-validation era operating on handcrafted dag-pb.","solutions":["Use 'ipfs dag patch rm-link' (IPLD dag-pb patch) for non-UnixFS dag-pb nodes","Re-create the node as a UnixFS directory if UnixFS semantics are wanted","Set --allow-non-unixfs / SkipUnixFSValidation=true to force the edit"],"exampleFix":"// before\nipfs object patch rm-link <dag-pb-node> oldlink\n// after\nipfs dag patch rm-link <dag-pb-node> -t <node> oldlink","handlingStrategy":"validation","validationCode":"if _, err := ft.FSNodeFromBytes(pbNode.Data()); err != nil {\n    // non-UnixFS dag-pb node: use 'ipfs dag patch' instead of RmLink\n}","typeGuard":"func isUnixFSNode(n ipld.Node) bool {\n\tpb, ok := n.(*dagpb.PBNode)\n\tif !ok { return false }\n\t_, err := ft.FSNodeFromBytes(pb.Data())\n\treturn err == nil\n}","tryCatchPattern":null,"preventionTips":["Keep dag-pb editing (object/dag patch) separate from UnixFS editing (files API)","Check node provenance: 'ipfs dag put' nodes are not UnixFS","Only enable --allow-non-unixfs for deliberate raw dag-pb surgery"],"tags":["unixfs","dag-pb","validation","deprecated-api"],"backgroundTag":"unixfs-non-directory-link-edit","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"}