ipfs/kubo · error

cannot return size for anything other than a DAG with a root

Error message

cannot return size for anything other than a DAG with a root CID

What it means

`ipfs dag stat` computes size/counts for a whole DAG identified by a root CID. If the requested path resolves with a remaining path segment (e.g. /ipfs/<cid>/a/b), there is no single root DAG to measure, so the command refuses with this error.

Source

Thrown at core/commands/dag/stat.go:63

	// just on remembering which CIDs were seen. On very large DAGs that second
	// copy has OOM-killed daemons running `dag stat` over multi-hundred-GiB
	// UnixFS roots, so allocate it only when there is more than one root.
	var cidSet *cid.Set
	if len(req.Arguments) > 1 {
		cidSet = cid.NewSet()
	}
	dagStatSummary := &DagStatSummary{DagStatsArray: []*DagStat{}}
	for _, a := range req.Arguments {
		p, err := cmdutils.PathOrCidPath(a)
		if err != nil {
			return err
		}
		rp, remainder, err := api.ResolvePath(req.Context, p)
		if err != nil {
			return err
		}
		if len(remainder) > 0 {
			return fmt.Errorf("cannot return size for anything other than a DAG with a root CID")
		}

		obj, err := nodeGetter.Get(req.Context, rp.RootCid())
		if err != nil {
			return err
		}
		dagstats := &DagStat{Cid: enc.Encode(rp.RootCid())}
		dagStatSummary.appendStats(dagstats)
		err = traverse.Traverse(obj, traverse.Options{
			DAG:   nodeGetter,
			Order: traverse.DFSPre,
			Func: func(current traverse.State) error {
				currentNodeSize := uint64(len(current.Node.RawData()))
				dagstats.Size += currentNodeSize
				dagstats.NumBlocks++
				// With a single root, boxo's SkipDuplicates guarantees each CID is
				// visited exactly once, so every block counts toward the global
				// unique total. With multiple roots, cidSet tracks which CIDs were

View on GitHub (pinned to 329838acdf)

Solutions

  1. Use only the root: `ipfs dag stat /ipfs/<cid>`
  2. Resolve the subpath to a CID first (e.g. `ipfs resolve /ipfs/<cid>/sub`) and stat that CID
  3. Use `ipfs files stat` or `ipfs ls` for path-based traversal info

Example fix

// before
ipfs dag stat /ipfs/bafy.../photos/img.png
// after
ipfs resolve /ipfs/bafy.../photos/img.png
# then
ipfs dag stat <resolved-cid>
Defensive patterns

Strategy: validation

Validate before calling

// strip path remainder to a root CID before dag stat
p := strings.TrimPrefix(pathStr, "/ipfs/")
root, rest, _ := strings.Cut(p, "/")
if rest != "" {
    out, _ := exec.Command("ipfs", "resolve", pathStr).Output()
    pathStr = strings.TrimSpace(string(out)) // now a bare CID path
}

Prevention

When it happens

Trigger: `ipfs dag stat /ipfs/<cid>/sub/path` — any path with components after the CID.

Common situations: Pasting a gateway-style deep path into dag stat; scripting that appends UnixFS path segments; intending `ipfs files stat` or `ipfs object stat` instead.

Related errors


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