kopia/kopia · error
error loading write epoch
Error message
error loading write epoch
What it means
loadWriteEpoch wraps a failure from blob.ListAllBlobs when enumerating epoch marker index blobs (EpochMarkerIndexBlobPrefix) to rebuild the CurrentSnapshot's write epoch state. Without listing these blobs the manager cannot determine the current write epoch or per-epoch start times, so snapshot loading fails.
Solutions
- Fix the wrapped storage error: verify blob store connectivity, credentials, and that the epoch marker index container/prefix exists.
- Confirm the storage prefix EpochMarkerIndexBlobPrefix matches where epoch markers were actually written (no version/migration drift).
- Retry snapshot loading — transient list failures clear once the backend recovers.
- Check storage backend quotas/throttling if the error is rate limiting.
Example fix
// before: fail startup hard on transient list error
if err := mgr.loadWriteEpoch(ctx, snapshot); err != nil { return err }
// after: brief retry for transient storage errors
err := mgr.loadWriteEpoch(ctx, snapshot)
if err != nil && isTransientStorage(err) {
time.Sleep(2 * time.Second)
err = mgr.loadWriteEpoch(ctx, snapshot)
} Defensive patterns
Strategy: retry
Validate before calling
// probe storage before snapshot load
if _, err := blob.ListAllBlobs(ctx, st, EpochMarkerIndexBlobPrefix); err != nil {
return fmt.Errorf("epoch marker index not listable: %w", err)
} Try / catch
if err := mgr.loadWriteEpoch(ctx, snapshot); err != nil {
if strings.Contains(err.Error(), "error loading write epoch") {
// storage list failure: check blob store health/credentials, retry after backoff
}
return err
} Prevention
- Verify blob store connectivity and credentials before node startup.
- Ensure the epoch marker index prefix/container exists in every environment.
- Monitor storage backend for throttling and quota exhaustion.
- Retry transient list errors during snapshot load with capped backoff.
When it happens
Trigger: Calling verifyCurrentWriteEpoch (or snapshot load via the anonymous caller) when the underlying blob storage returns an error listing blobs under the EpochMarkerIndex prefix — storage outage, permission failure, malformed store response.
Common situations: Blob store connectivity loss or expired credentials during node startup; bucket/container missing or renamed after migration; storage backend returning throttling/5xx errors that ListAllBlobs does not absorb.
Understand the failure class
Background: Database query failed: Internal Server Error 500s wrapping SQL, Prisma, and connection failures — what to check first — this error's family across 16 libraries.
Related errors
- epoch manager
- error getting committed state
- failed to list policies
- unable to flush old pending writes
- Attributes
AI-assisted analysis of kopia/kopia@82495e54b5 (2026-09-07).
Data as JSON: /api/errors/2516e363a1676c99.
Report an issue: GitHub.
Appendix: source
Thrown at internal/epoch/epoch_manager.go:499
for err := e.refreshAttemptLocked(ctx); err != nil; err = e.refreshAttemptLocked(ctx) {
if ctx.Err() != nil {
return errors.Wrap(ctx.Err(), "refreshAttemptLocked")
}
contentlog.Log2(ctx, e.log, "refresh attempt failed", logparam.Error("error", err), logparam.Duration("nextDelayTime", nextDelayTime))
time.Sleep(nextDelayTime)
nextDelayTime = min(time.Duration(float64(nextDelayTime)*maxRefreshAttemptSleepExponent), maxRefreshAttemptSleep)
}
return nil
}
func (e *Manager) loadWriteEpoch(ctx context.Context, cs *CurrentSnapshot) error {
blobs, err := blob.ListAllBlobs(ctx, e.st, EpochMarkerIndexBlobPrefix)
if err != nil {
return errors.Wrap(err, "error loading write epoch")
}
for epoch, bm := range groupByEpochNumber(blobs) {
cs.EpochStartTime[epoch] = bm[0].Timestamp
if epoch > cs.WriteEpoch {
cs.WriteEpoch = epoch
}
}
cs.EpochMarkerBlobs = blobs
return nil
}
func (e *Manager) loadDeletionWatermark(ctx context.Context, cs *CurrentSnapshot) error {
blobs, err := blob.ListAllBlobs(ctx, e.st, DeletionWatermarkBlobPrefix)
if err != nil {View on GitHub (pinned to 82495e54b5)