ipfs/kubo · error
reading new root block: %w
Error message
reading new root block: %w
What it means
When the new root block does exist locally, `ipfs files chroot` reads it from the blockstore; a failure at bs.Get (datastore I/O error, block vanished between Has and Get) is wrapped with this message. The block is then decoded as protobuf/FSNode, with separate errors for non-dag-pb or non-directory payloads.
Source
Thrown at core/commands/files.go:1784
// Check new root exists locally and is a directory
hasBlock, err := bs.Has(req.Context, newRootCid)
if err != nil {
return fmt.Errorf("checking if new root exists: %w", err)
}
if !hasBlock {
// Special case: empty dir is always available (hardcoded in boxo)
emptyDirCid := ft.EmptyDirNode().Cid()
if !newRootCid.Equals(emptyDirCid) {
return fmt.Errorf("new root %s does not exist locally; fetch it first with 'ipfs block get'", enc.Encode(newRootCid))
}
}
// Validate it's a directory (not a file)
if hasBlock {
blk, err := bs.Get(req.Context, newRootCid)
if err != nil {
return fmt.Errorf("reading new root block: %w", err)
}
pbNode, err := dag.DecodeProtobuf(blk.RawData())
if err != nil {
return fmt.Errorf("new root is not a valid dag-pb node: %w", err)
}
fsNode, err := ft.FSNodeFromBytes(pbNode.Data())
if err != nil {
return fmt.Errorf("new root is not a valid UnixFS node: %w", err)
}
if fsNode.Type() != ft.TDirectory && fsNode.Type() != ft.THAMTShard {
return fmt.Errorf("new root must be a directory, got %s", fsNode.Type())
}
}
// Get old root for display (if exists)
var oldRootStr string
oldRootBytes, err := localDS.Get(req.Context, node.FilesRootDatastoreKey)
if err == nil {View on GitHub (pinned to 329838acdf)
Solutions
- Verify the datastore health (check daemon logs, run `ipfs repo fsck`-style checks or inspect disk errors) and retry.
- Re-fetch the block (`ipfs block get <cid>` with the daemon up) to restore/replace a corrupted copy.
- Confirm the CID names a UnixFS directory node (`ipfs dag get <cid>` / `ipfs files stat` on an added dir) before chrooting.
Example fix
# before ipfs files chroot --confirm <cid-of-raw-block> # reading/decoding fails # after CID=$(ipfs add -Q --only-hash mydir/ ) # ensures UnixFS directory DAG ipfs block get "$CID" > /dev/null && ipfs shutdown ipfs files chroot --confirm "$CID"
Defensive patterns
Strategy: retry
Validate before calling
ipfs dag get "$CID" > /dev/null 2>&1 || echo "not a readable dag-pb node"
Type guard
func isDirNode(c cid.Cid) bool { return c.Type() == cid.DagProtobuf } Try / catch
if _, err := bs.Get(ctx, cid); err != nil {
// transient (GC race) -> re-fetch block via block get, then retry chroot
} Prevention
- Pin the root CID to keep GC from deleting it between Has and Get
- Verify the target is a UnixFS directory DAG, not a raw/file node
- Monitor datastore health (disk space, flatfs/badger errors) before repo-level operations
When it happens
Trigger: Datastore read failure during bs.Get (corruption, disk error, concurrent GC removing the block between Has and Get); the CID pointing to a raw/other-codec block instead of a UnixFS dag-pb node (raised by the subsequent DecodeProtobuf/FSNodeFromBytes wraps in the same region).
Common situations: A concurrent `ipfs repo gc` deleting unpinned blocks while chroot runs; damaged flatfs/badger shards; passing a CID of a raw block or file where a directory node is required.
Related errors
- aborted: %s
- some blocks not removed
- can't convert non-dag-pb nodes to cidv0
- failed to open repo: %w
- key not found: %s
AI-assisted analysis of ipfs/kubo@329838acdf (2026-09-03).
Data as JSON: /api/errors/b34c13f1f554ba65.
Report an issue: GitHub.