kopia/kopia · error

failed to rewrite contents

Error message

failed to rewrite %v contents

What it means

RewriteContents tracks a counter (failedCount) of contents that could not be rewritten. If any failures occurred, it skips the flush and returns this error reporting how many contents failed to rewrite. It is a deliberate aggregate-failure signal rather than an unexpected exception.

Solutions

  1. Check logs emitted by the rewrite workers to identify which contents failed and why.
  2. Re-run the rewrite command after fixing the underlying cause; contents that succeed are persisted incrementally.
  3. If packs are missing or corrupted, restore them from replication/backup or drop unreferenced contents via repair tools.
  4. If failures are confined to stale/deleted contents, investigate whether those contents should be excluded or the repo needs deeper repair (e.g. 'kopia repository repair').

Example fix

// before: abort entirely when any content fails
return nil, errors.Errorf("failed to rewrite %v contents", failedCount.Load())
// after: log failures and allow forcing a flush of successful rewrites
if failedCount.Load() > 0 {
    log.Warnf("failed to rewrite %v contents", failedCount.Load())
    if opt.IgnoreFailures {
        if err := rep.ContentManager().Flush(ctx); err != nil {
            return nil, errors.Wrap(err, "error flushing repo")
        }
        return result, nil
    }
    return nil, errors.Errorf("failed to rewrite %v contents", failedCount.Load())
}
Defensive patterns

Strategy: try-catch

Validate before calling

// pre-verify the contents that would be rewritten
opts := &repo.VerifyContentsOptions{IncludeDeletedContents: true}
if err := rep.VerifyContents(ctx, opts); err != nil {
    return errors.Wrap(err, "repository has unreadable contents; repair before rewrite")
}

Try / catch

_, err := RewriteContents(ctx, rep, opt)
if err != nil {
    var nFailed int
    if _, scanErr := fmt.Sscanf(err.Error(), "failed to rewrite %d contents", &nFailed); scanErr == nil && nFailed > 0 {
        // some contents failed; inspect logs for which IDs failed, fix cause, re-run
        log.Errorf("%d contents failed to rewrite; run verify/repair then retry", nFailed)
        return err
    }
    return err
}

Prevention

When it happens

Trigger: Any content queued by getContentToRewrite fails to rewrite — e.g. its underlying pack blob is missing/corrupted, content info lookup fails, or the rewrite worker encounters storage errors — so failedCount.Load() > 0 at the end of the run.

Common situations: Repository with corrupted or deleted pack files; partial content-info lookups failing for old contents; storage backend errors affecting a subset of blobs during a long-running full maintenance rewrite.

Related errors


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

Appendix: source

Thrown at repo/maintenance/content_rewrite.go:163

		ToRewriteContentCount: uint64(toRewriteCount),
		ToRewriteContentSize:  maintenancestats.ToUint64(toRewriteBytes),
		RewrittenContentCount: uint64(rewrittenCount),
		RewrittenContentSize:  maintenancestats.ToUint64(rewrittenBytes),
		RetainedContentCount:  uint64(retainedCount),
		RetainedContentSize:   maintenancestats.ToUint64(retainedBytes),
	}

	contentlog.Log1(ctx, log, "Rewritten contents", result)

	if failedCount.Load() == 0 {
		if err := rep.ContentManager().Flush(ctx); err != nil {
			return nil, errors.Wrap(err, "error flushing repo")
		}

		return result, nil
	}

	return nil, errors.Errorf("failed to rewrite %v contents", failedCount.Load())
}

func getContentToRewrite(ctx context.Context, rep repo.DirectRepository, opt *RewriteContentsOptions) <-chan contentInfoOrError {
	ch := make(chan contentInfoOrError)

	go func() {
		defer close(ch)

		// get content IDs listed on command line
		findContentInfos(ctx, rep, ch, opt.ContentIDs)

		// add all content IDs from short packs
		if opt.ShortPacks {
			mp, mperr := rep.ContentReader().ContentFormat().GetMutableParameters(ctx)
			if mperr == nil {
				threshold := int64(mp.MaxPackSize * shortPackThresholdPercent / 100) //nolint:mnd
				findContentInShortPacks(ctx, rep, ch, threshold, opt)
			}

View on GitHub (pinned to 82495e54b5)