kopia/kopia · error

error to advance epoch in quick epoch maintenance task

Error message

error to advance epoch in quick epoch maintenance task

What it means

Wraps the error returned by runTaskEpochAdvance when it is called at the end of runTaskEpochMaintenanceQuick. The single-epoch compaction succeeded but advancing the write epoch marker failed. The message is purely a wrapper; the cause is whatever 'error advancing epoch marker' wrapped.

Solutions

  1. Inspect errors.RootCause for the epoch-manager failure detail.
  2. Re-run maintenance — the next pass will retry epoch advancement.
  3. Serialize maintenance runs across hosts via the repository's maintenance lock.
  4. Check storage write permissions for the epoch marker prefix.
Defensive patterns

Strategy: retry

Try / catch

if err := rep.Maintenance.Run(ctx, maintenance.ModeQuick); err != nil {
    log.Printf("epoch advance deferred: %v", err) // next run retries
}

Prevention

When it happens

Trigger: runTaskEpochMaintenanceQuick (from runQuickMaintenance) runs MaybeCompactSingleEpoch successfully, then calls runTaskEpochAdvance whose MaybeAdvanceWriteEpoch fails, e.g. marker write failure or epoch conflict.

Common situations: Two hosts running quick maintenance concurrently; storage throttling or transient outage right after compaction; read-only storage preventing marker update.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


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

Appendix: source

Thrown at repo/maintenance/maintenance_run.go:372

		return stats, errors.Wrap(err, "error advancing epoch marker")
	})
}

func runTaskEpochMaintenanceQuick(ctx context.Context, em *epoch.Manager, runParams RunParameters, s *Schedule) error {
	err := reportRunAndMaybeCheckContentIndex(ctx, runParams.rep, TaskEpochCompactSingle, s, func() (maintenancestats.Kind, error) {
		userLog(ctx).Info("Compacting an eligible uncompacted epoch...")

		stats, err := em.MaybeCompactSingleEpoch(ctx)

		return stats, errors.Wrap(err, "error compacting single epoch")
	})
	if err != nil {
		return err
	}

	err = runTaskEpochAdvance(ctx, em, runParams, s)

	return errors.Wrap(err, "error to advance epoch in quick epoch maintenance task")
}

func runTaskEpochMaintenanceFull(ctx context.Context, runParams RunParameters, s *Schedule) error {
	em, hasEpochManager, emerr := runParams.rep.ContentManager().EpochManager(ctx)
	if emerr != nil {
		return errors.Wrap(emerr, "epoch manager")
	}

	if !hasEpochManager {
		return nil
	}

	// compact a single epoch
	if err := reportRunAndMaybeCheckContentIndex(ctx, runParams.rep, TaskEpochCompactSingle, s, func() (maintenancestats.Kind, error) {
		userLog(ctx).Info("Compacting an eligible uncompacted epoch...")

		stats, err := em.MaybeCompactSingleEpoch(ctx)

View on GitHub (pinned to 82495e54b5)