kopia/kopia · error
unable to get snapshot root for
Error message
unable to get snapshot root for %v
What it means
CalculateStorageStats wraps a failure from SnapshotRoot(rep, snap) with "unable to get snapshot root for %v" where %v is "source@startTime". SnapshotRoot loads the root directory entry of a snapshot manifest from the repository object store; if the root object ID cannot be resolved or read, stats computation stops for the whole manifest list.
Solutions
- Inspect the wrapped error: if it is object-not-found for the root object, the snapshot is broken — remove it from the manifests slice and continue with the rest.
- Run repository consistency tools (kopia repository verify / maintenance) to repair or prune damaged snapshots.
- Confirm the manifests were produced from the same repo (rep) you pass in; mixing repos yields unresolvable root entries.
- Guard the call: fetch SnapshotRoot yourself first and skip manifests whose root cannot be loaded instead of failing the entire batch.
Example fix
// before
err := CalculateStorageStats(ctx, rep, allManifests, cb) // fails on one bad snapshot
// after
var valid []*snapshot.Manifest
for _, m := range allManifests {
if _, err := SnapshotRoot(rep, m); err == nil {
valid = append(valid, m)
}
}
err := CalculateStorageStats(ctx, rep, valid, cb) Defensive patterns
Strategy: validation
Validate before calling
for _, m := range manifests {
if _, err := SnapshotRoot(rep, m); err != nil {
return fmt.Errorf("snapshot %v has unreadable root: %w", m.ID, err)
}
} Type guard
func hasRoot(rep repo.Repository, m *snapshot.Manifest) bool {
_, err := SnapshotRoot(rep, m)
return err == nil
} Try / catch
err := CalculateStorageStats(ctx, rep, manifests, cb)
if err != nil && strings.Contains(err.Error(), "unable to get snapshot root") {
// skip/filter broken manifests and retry
} Prevention
- Always pass manifests and repo from the same repository/config.
- Run regular kopia maintenance to prevent object pruning of live snapshots.
- Never manually delete blobs from the storage backend.
When it happens
Trigger: Calling CalculateStorageStats with a manifest whose root object ID points to a missing/corrupted object, or whose RootEntry cannot be loaded (e.g. deleted or pruned underlying objects), causing SnapshotRoot to return an error.
Common situations: Repository corruption or blobs deleted by aggressive maintenance; a manifest from a different repository/store than the one passed in; partial restore/migration where the snapshot metadata exists but the referenced root object is gone.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
- a snapshot time is needed to use a path as source
- <child name>
- error estimating
- error getting filesystem entry for
- error getting snapshot root entry
AI-assisted analysis of kopia/kopia@82495e54b5 (2026-09-07).
Data as JSON: /api/errors/8cbe2c34fec41da3.
Report an issue: GitHub.
Appendix: source
Thrown at snapshot/snapshotfs/snapshot_storage_stats.go:97
return nil
},
})
if twerr != nil {
return errors.Wrap(twerr, "tree walker")
}
defer tw.Close(ctx)
src := manifests[0].Source
for _, snap := range manifests {
*unique = snapshot.StorageUsageDetails{}
rootName := src.String() + "@" + snap.StartTime.Format(time.RFC3339)
root, err := SnapshotRoot(rep, snap)
if err != nil {
return errors.Wrapf(err, "unable to get snapshot root for %v", rootName)
}
if err := tw.Process(ctx, root, rootName); err != nil {
return errors.Wrapf(err, "error processing %v", rootName)
}
snap.StorageStats = &snapshot.StorageStats{
NewData: *unique,
RunningTotal: *runningTotal,
}
if err := callback(snap); err != nil {
return err
}
}
return nil
}View on GitHub (pinned to 82495e54b5)