ipfs/kubo · error
%w: %v
Error message
%w: %v
What it means
The source CID is dag-pb but the dag-pb block's embedded UnixFS data failed to parse (ft.FSNodeFromBytes error), so it is not a valid UnixFS node. The error message renders as "cp: source must be a valid UnixFS (dag-pb or raw codec): <parse error>" — the %w wraps errFilesCpInvalidUnixFS so errors.Is against it still matches.
Source
Thrown at core/commands/files.go:562
node, err := getNodeFromPath(req.Context, nd, api, src)
if err != nil {
return fmt.Errorf("cp: cannot get node from path %s: %s", src, err)
}
// Sanity-check: ensure root CID is a valid UnixFS (dag-pb or raw block)
// Context: https://github.com/ipfs/kubo/issues/10331
srcCidType := node.Cid().Type()
switch srcCidType {
case cid.Raw:
if _, ok := node.(*dag.RawNode); !ok {
return errFilesCpInvalidUnixFS
}
case cid.DagProtobuf:
if _, ok := node.(*dag.ProtoNode); !ok {
return errFilesCpInvalidUnixFS
}
if _, err = ft.FSNodeFromBytes(node.(*dag.ProtoNode).Data()); err != nil {
return fmt.Errorf("%w: %v", errFilesCpInvalidUnixFS, err)
}
default:
return errFilesCpInvalidUnixFS
}
mkParents, _ := req.Options[filesParentsOptionName].(bool)
if mkParents {
maxDirLinks := int(cfg.Import.UnixFSDirectoryMaxLinks.WithDefault(config.DefaultUnixFSDirectoryMaxLinks))
sizeEstimationMode := cfg.Import.HAMTSizeEstimationMode()
err := ensureContainingDirectoryExists(nd.FilesRoot, dst,
mfs.WithCidBuilder(prefix),
mfs.WithMaxLinks(maxDirLinks),
mfs.WithSizeEstimationMode(sizeEstimationMode),
)
if err != nil {
return err
}
}View on GitHub (pinned to 329838acdf)
Solutions
- Confirm the block is real UnixFS: `ipfs dag get <cid> | head` or `ipfs ls /ipfs/<cid>` (ls works only on UnixFS)
- Re-add the original bytes with `ipfs add` to get a proper UnixFS dag-pb node
- If the content is a raw dag-pb IPLD document, it cannot be placed in MFS; export and re-add as a file
- Use `ipfs files cp` only with CIDs produced by `ipfs add` or raw blocks
Example fix
// before: dag-put output copied into MFS ipfs dag put --store-codec dag-pb data.pb ipfs files cp /ipfs/<cid> /my-file // fails // after ipfs add -q data ipfs files cp /ipfs/<new-cid> /my-file
Defensive patterns
Strategy: validation
Validate before calling
// dag-pb CIDs must come from ipfs add (UnixFS), not dag put
if isDagPbButFromDagPut(cid) {
return fmt.Errorf("re-add content with `ipfs add` before files cp")
} Type guard
func isValidUnixFSDagPb(cid string) bool {
// `ipfs ls` succeeds only on UnixFS dag-pb nodes
return run("ipfs", "ls", "/ipfs/"+cid) == nil
} Try / catch
if err := ipfsFilesCp(src, dst); err != nil {
if errors.Is(err, errFilesCpInvalidUnixFS) {
// export original bytes and re-add with `ipfs add`
}
} Prevention
- Never feed `ipfs dag put` output directly into `ipfs files cp`
- Validate with `ipfs ls /ipfs/<cid>` first — it only works on UnixFS
- Track CID provenance: prefer `ipfs add`-produced CIDs for MFS ops
When it happens
Trigger: Running `ipfs files cp /ipfs/<cid> /dst` where <cid> is dag-pb but its protobuf data is not a valid UnixFS FSNode — e.g. a bare dag-pb IPLD document that was created with `ipfs dag put` (no unixfs encoding) rather than `ipfs add`.
Common situations: Putting arbitrary protobuf data with `ipfs dag put --store-codec dag-pb` and then trying to cp it into MFS; corrupted dag-pb blocks; hand-crafted dag-pb documents without UnixFS Data field.
Related errors
- unrecognized node type: %s
- cp: source must be a valid UnixFS (dag-pb or raw codec)
- unexpected Objects len
- %s can't be used with UnixFS metadata like mode or modificat
- %s and %s options are not compatible
AI-assisted analysis of ipfs/kubo@329838acdf (2026-09-03).
Data as JSON: /api/errors/44c14aa280071a5f.
Report an issue: GitHub.