ipfs/kubo · error

error traversing DAG

Error message

error traversing DAG: %w

What it means

`ipfs dag stat` walks the DAG with an ipld-prime traverser to count blocks and sizes. If the traversal itself fails (missing blocks, decode errors, link errors), the command wraps the traversal error as `error traversing DAG: %w`.

Solutions

  1. Ensure the node is online and the full DAG is fetchable, or import the complete CAR first
  2. Read the wrapped inner error: block-not-found means fetch data; decode errors mean corrupt data
  3. Use `ipfs dag stat --local` only when the full DAG is known present locally
  4. Re-add/re-import from a verified source if blocks are corrupt

Example fix

// before
ipfs dag stat /ipfs/<cid>   # offline node, partial data
// after
ipfs dag import full.car    # or start daemon
ipfs dag stat /ipfs/<cid>
Defensive patterns

Strategy: try-catch

Validate before calling

// check local availability first when offline
if offline {
    if out, err := exec.Command("ipfs", "dag", "stat", "--local", path).Output(); err != nil {
        return fmt.Errorf("DAG incomplete locally: %s", out)
    }
}

Try / catch

// CLI: parse wrapped traversal cause
if err := run("ipfs", "dag", "stat", path); err != nil {
    if strings.Contains(errText(err), "not found") {
        // start daemon / fetch DAG, then retry
        return retryAfterFetch(path)
    }
    return err
}

Prevention

When it happens

Trigger: Missing blocks (offline node without the full DAG), undecodable nodes, or a bad link encountered during `ipfs dag stat`.

Common situations: Running dag stat offline/on a node without the data (`context deadline exceeded` or "block not found" wrapped inside); partial imports with --local-only followed by stat without --local; corrupted blocks.

Related errors


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

Appendix: source

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

				// unique total. With multiple roots, cidSet tracks which CIDs were
				// already counted under a previous root (Visit reports true the
				// first time a CID is seen).
				if cidSet == nil || cidSet.Visit(current.Node.Cid()) {
					dagStatSummary.incrementTotalSize(currentNodeSize)
				}
				dagStatSummary.incrementRedundantSize(currentNodeSize)
				if progressive {
					if err := res.Emit(dagStatSummary); err != nil {
						return err
					}
				}
				return nil
			},
			ErrFunc:        nil,
			SkipDuplicates: true,
		})
		if err != nil {
			return fmt.Errorf("error traversing DAG: %w", err)
		}
	}

	if cidSet != nil {
		dagStatSummary.UniqueBlocks = cidSet.Len()
	} else {
		// Single root: boxo deduplicated within the traversal, so the number of
		// unique blocks equals the number of blocks visited.
		for _, ds := range dagStatSummary.DagStatsArray {
			dagStatSummary.UniqueBlocks += int(ds.NumBlocks)
		}
	}
	dagStatSummary.calculateSummary()

	if err := res.Emit(dagStatSummary); err != nil {
		return err
	}
	return nil

View on GitHub (pinned to 329838acdf)