juicedata/juicefs · critical
The entry of the root inode was not found
Error message
The entry of the root inode was not found
What it means
During kvMeta.Load (V1 dump-format loading) in the TKV metadata engine, the code looks up the entry for root inode 1; if the tree record is missing or has no Attr, it refuses to continue. This means the loaded snapshot is not a valid JuiceFS metadata tree (root inode absent) or the load was given a malformed/empty key-range.
Source
Thrown at pkg/meta/tkv.go:4097
}
if err = m.dumpEntry(root, tree, nil); err != nil {
return err
}
if root == RootInode && !skipTrash {
trash = &DumpedEntry{
Attr: &DumpedAttr{
Inode: TrashInode,
Type: "directory",
},
}
if err = m.dumpEntry(TrashInode, trash, nil); err != nil {
return err
}
}
}
if tree == nil || tree.Attr == nil {
return errors.New("The entry of the root inode was not found")
}
tree.Name = "FSTree"
var rs [][]byte
err = m.txn(Background(), func(tx *kvTxn) error {
rs = tx.gets(m.counterKey(usedSpace),
m.counterKey(totalInodes),
m.counterKey("nextInode"),
m.counterKey("nextChunk"),
m.counterKey("nextSession"),
m.counterKey("nextTrash"))
return nil
})
if err != nil {
return err
}
cs := make([]int64, len(rs))
for i, r := range rs {View on GitHub (pinned to c9a67b23e8)
Solutions
- Verify the backup file is a complete, unmodified juicefs dump that contains the root inode (inode 1) entry; re-dump from the source volume if it was truncated.
- Check the dump/load filter options (paths/inode ranges) — ensure the load actually includes the FSTree/root entry instead of a partial subtree.
- Confirm dump/load format compatibility between the client versions producing and consuming the backup; upgrade the loading client if the dump is from a newer version.
- If the target engine is not empty, check for conflicting partial loads; wipe the target and retry with a verified backup.
Example fix
// before (loading a filtered backup that dropped root) juicefs load redis://127.0.0.1:6379/1 partial.dump // after (verify root entry exists, then load full backup) grep -m1 '"inode":1' full.dump juicefs load redis://127.0.0.1:6379/1 full.dump
Defensive patterns
Strategy: validation
Validate before calling
import "encoding/json"
func backupHasRootInode(dump []byte) bool {
for _, line := range bytes.Split(dump, []byte("\n")) {
var rec struct{ Inode Ino `json:"inode"` }
if json.Unmarshal(line, &rec) == nil && rec.Inode == 1 {
return true
}
}
return false
} Prevention
- Always produce backups with juicefs dump; never hand-edit or partially copy dump files.
- Verify a backup restores into a scratch engine before trusting it.
- Pin matching client versions for dump and load across mixed-version clusters.
When it happens
Trigger: Calling juicefs load (kvMeta.Load) against a backup file that lacks the root inode (inode 1) entry, loading a corrupted or truncated dump, or loading data dumped with an incompatible/older format into a TKV engine (TiKV/etcd/Badger/FoundationDB).
Common situations: Restoring a manually edited or partially copied backup; loading a dump produced from a different tool/format; mixing versions where the dump predates fields the loader requires; loading into an empty engine from a file whose tree segment was lost.
Understand the failure class
Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.
Related errors
- failed to get startTS, which is required for TiKV to ensure
- not implemented, use kvMeta.LoadMetaV2 instead
- database %s is used by volume %s
- failed to read footer: %w
- unknown message type %d
AI-assisted analysis of juicedata/juicefs@c9a67b23e8 (2026-09-06).
Data as JSON: /api/errors/208598fc1b3be2ec.
Report an issue: GitHub.