kopia/kopia · error

error copying blobs

Error message

error copying blobs

What it means

This is the outer wrapper around errgroup.Wait() in runSyncBlobs for 'repository sync to'. It aggregates any error returned by the parallel copy/delete worker goroutines (which are already wrapped with 'error copying <id>' or 'error deleting <id>'), so the developer sees the sync's blob-transfer phase failed; the specific BLOB and root cause are in the wrapped chain.

Solutions

  1. Re-run the sync; it is idempotent and will resume with the BLOBs still missing at the destination
  2. Look at the inner 'error copying <blobID>'/'error deleting <blobID>' and underlying cause for the actual fix
  3. Reduce parallelism or check network stability if throttling/timeouts caused the failure
  4. Fix destination permissions/quotas before retrying if the inner error indicates access or capacity issues

Example fix

// before: transient failure aborts run
kopia repository sync to s3 --bucket=dest   // fails: error copying blobs -> error copying abc123
// after: simply retry, sync resumes
kopia repository sync to s3 --bucket=dest
Defensive patterns

Strategy: retry

Try / catch

if err := kopiaSyncTo(ctx, opts); err != nil {
    if strings.Contains(err.Error(), "error copying blobs") {
        log.Printf("sync aborted mid-transfer: %v; retrying (idempotent)", err)
        return retryWithBackoff(ctx, kopiaSyncTo, opts)
    }
    return err
}

Prevention

When it happens

Trigger: Any of the worker goroutines in runSyncBlobs returns an error: a syncCopyBlob failure on copyCh items or a syncDeleteBlob failure on deleteCh items; the first error cancels the errgroup context and stops the remaining workers.

Common situations: Mid-sync network outage to source or destination; destination storage throttling under parallelism; permission errors surfacing during copy or delete phases; Ctrl-C / context cancellation mid-run.

Related errors


AI-assisted analysis of kopia/kopia@82495e54b5 (2026-09-07). Data as JSON: /api/errors/3a0699eb9c7bae9b. Report an issue: GitHub.

Appendix: source

Thrown at cli/command_repository_sync.go:283

						numBlobs, units.BytesString(bytesCopied), speed, eta))

				progressMutex.Unlock()
			}

			for m := range deleteCh {
				log(ctx).Debugf("[%v] Deleting %v (%v bytes)...\n", workerID, m.BlobID, m.Length)

				if err := syncDeleteBlob(ctx, m, dst); err != nil {
					return errors.Wrapf(err, "error deleting %v", m.BlobID)
				}
			}

			return nil
		})
	}

	if err := eg.Wait(); err != nil {
		return errors.Wrap(err, "error copying blobs")
	}

	return nil
}

func sliceToChannel(ctx context.Context, md []blob.Metadata) chan blob.Metadata {
	ch := make(chan blob.Metadata)

	go func() {
		defer close(ch)

		for _, it := range md {
			select {
			case ch <- it:
			case <-ctx.Done():
				return
			}
		}

View on GitHub (pinned to 82495e54b5)