kopia/kopia · error
can't retrieve sources
Error message
can't retrieve sources
What it means
kopia's `snapshot migrate` command wraps failures from getSourcesToMigrate, which lists the snapshots/sources available in the source repository, with the message "can't retrieve sources". It means the migration could not even enumerate what to copy — the failure happens before any snapshot data is transferred. The underlying cause (repository access, manifest listing, etc.) is in the wrapped error chain.
Solutions
- Read the wrapped cause with `kopia logs` or --log-level=debug to see the root error and fix it (network, permissions, corruption).
- Verify the source repository is healthy: run `kopia repository status` and `kopia snapshot list` against the source config manually.
- Re-run after confirming network connectivity to the source repository backend (S3/Blob/SFTP etc.).
- If manifests are corrupted, run `kopia blobs list --verify` / repair tools on the source repository before migrating.
Example fix
// before
sources, err := c.getSourcesToMigrate(ctx, sourceRepo)
if err != nil {
return errors.Wrap(err, "can't retrieve sources")
}
// after: add retry for transient listing failures
var sources []snapshot.SourceInfo
err := retry.OnError(ctx, retry.Always, func() error {
var e error
sources, e = c.getSourcesToMigrate(ctx, sourceRepo)
return e
})
if err != nil {
return errors.Wrap(err, "can't retrieve sources")
} Defensive patterns
Strategy: retry
Validate before calling
// pre-check source repo is listable before migrating
if err := exec.Command("kopia", "--config-file", srcCfg, "snapshot", "list").Run(); err != nil {
return fmt.Errorf("source repo not listable: %w", err)
} Try / catch
// Go: inspect wrapped cause before giving up
if _, err := runMigrate(ctx); err != nil {
if errors.Is(err, context.DeadlineExceeded) || isTransient(err) {
// retry with backoff
}
log.Fatalf("migrate failed: %v", err)
} Prevention
- Always verify the source repository opens and lists snapshots before scripting migrations.
- Run migrations on a stable network connection; avoid spot-instance preemption windows.
- Check kopia logs at debug level after any migration failure to capture the wrapped root cause.
When it happens
Trigger: Running `kopia snapshot migrate` where the call to c.getSourcesToMigrate(ctx, sourceRepo) returns a non-nil error, typically because snapshot.ListSnapshots fails against the just-opened source repository.
Common situations: Source repository connectivity drops right after opening (network repo), corrupted manifest data in the source repo, insufficient permissions to read manifests, or a source repo opened in read-only/broken state.
Understand the failure class
Background: "API request failed": what wrapped HTTP errors from external APIs mean and how to find the real cause — this error's family across 29 libraries.
Related errors
- epoch manager
- error computing repository token
- error connecting
- error connecting to repository
- error creating manifest manager
AI-assisted analysis of kopia/kopia@82495e54b5 (2026-09-07).
Data as JSON: /api/errors/e70a6ba6159f8441.
Report an issue: GitHub.
Appendix: source
Thrown at cli/command_snapshot_migrate.go:58
cmd.Flag("parallel", "Number of sources to migrate in parallel").Default("1").IntVar(&c.migrateParallel)
cmd.Flag("apply-ignore-rules", "When migrating also apply current ignore rules").BoolVar(&c.applyIgnoreRules)
cmd.Action(svc.repositoryWriterActionWithMaintenance(c.run))
c.svc = svc
c.out.setup(svc)
}
func (c *commandSnapshotMigrate) run(ctx context.Context, destRepo repo.RepositoryWriter) error {
sourceRepo, err := c.openSourceRepo(ctx)
if err != nil {
return errors.Wrap(err, "can't open source repository")
}
defer sourceRepo.Close(ctx) //nolint:errcheck
sources, err := c.getSourcesToMigrate(ctx, sourceRepo)
if err != nil {
return errors.Wrap(err, "can't retrieve sources")
}
semaphore := make(chan struct{}, c.migrateParallel)
var (
wg sync.WaitGroup
mu sync.Mutex
canceled bool
activeUploaders = map[snapshot.SourceInfo]*upload.Uploader{}
)
c.svc.getProgress().StartShared()
c.svc.onTerminate(func() {
mu.Lock()
defer mu.Unlock()
if canceled {View on GitHub (pinned to 82495e54b5)