ipfs/kubo · error

cannot remove links from a non-UnixFS dag-pb node; pass --al

Error message

cannot remove links from a non-UnixFS dag-pb node; pass --allow-non-unixfs to skip validation

What it means

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.

Source

Thrown at core/coreapi/object.go:138

		return path.ImmutablePath{}, err
	}

	baseNd, err := api.core().ResolveNode(ctx, base)
	if err != nil {
		return path.ImmutablePath{}, err
	}

	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())
		}

View on GitHub (pinned to 329838acdf)

Solutions

  1. Use 'ipfs dag patch rm-link' (IPLD dag-pb patch) for non-UnixFS dag-pb nodes
  2. Re-create the node as a UnixFS directory if UnixFS semantics are wanted
  3. Set --allow-non-unixfs / SkipUnixFSValidation=true to force the edit

Example fix

// before
ipfs object patch rm-link <dag-pb-node> oldlink
// after
ipfs dag patch rm-link <dag-pb-node> -t <node> oldlink
Defensive patterns

Strategy: validation

Validate before calling

if _, err := ft.FSNodeFromBytes(pbNode.Data()); err != nil {
    // non-UnixFS dag-pb node: use 'ipfs dag patch' instead of RmLink
}

Type guard

func isUnixFSNode(n ipld.Node) bool {
	pb, ok := n.(*dagpb.PBNode)
	if !ok { return false }
	_, err := ft.FSNodeFromBytes(pb.Data())
	return err == nil
}

Prevention

When it happens

Trigger: 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).

Common situations: 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.

Related errors


AI-assisted analysis of ipfs/kubo@329838acdf (2026-09-03). Data as JSON: /api/errors/8cc099dc57ceaa4f. Report an issue: GitHub.