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

  1. Read the wrapped cause with `kopia logs` or --log-level=debug to see the root error and fix it (network, permissions, corruption).
  2. Verify the source repository is healthy: run `kopia repository status` and `kopia snapshot list` against the source config manually.
  3. Re-run after confirming network connectivity to the source repository backend (S3/Blob/SFTP etc.).
  4. 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

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


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)