t8y2/dbx · error

ETCD_COMPACTED

ETCD_COMPACTED

Error message

ETCD_COMPACTED: requested history was compacted at revision 

What it means

The initial Get that anchors the history query (WithRev at endRevision) failed with etcd's ErrCompacted, meaning the requested revision precedes the cluster's compaction boundary and its MVCC history has been discarded. The library then probes the compaction revision with a rev-1 watch and reports it in the message; if the probe fails it falls back to the generic ETCD_COMPACTED message (error 335).

Source

Thrown at agents/drivers/etcd-go/history.go:67

	if limit < 1 {
		limit = 1
	}
	if limit > historyLimitMax {
		limit = historyLimitMax
	}
	requestedEnd := longOrNull(params, "endRevision")

	ctx, cancel := context.WithTimeout(context.Background(), rpcTimeoutSeconds*time.Second)
	latestOptions := []clientv3.OpOption{}
	if requestedEnd != nil && *requestedEnd > 0 {
		latestOptions = append(latestOptions, clientv3.WithRev(*requestedEnd))
	}
	latest, err := client.Get(ctx, key, latestOptions...)
	cancel()
	if err != nil {
		if errors.Is(err, rpctypes.ErrCompacted) {
			if revision, ok := compactedRevisionOf(client, key); ok {
				return nil, errors.New("ETCD_COMPACTED: requested history was compacted at revision " + longString(revision))
			}
			return nil, errors.New("ETCD_COMPACTED: requested history was compacted")
		}
		return nil, err
	}
	var endRevision int64
	if requestedEnd != nil {
		endRevision = *requestedEnd
	} else {
		endRevision = latest.Header.Revision
	}
	var targetKeyRevision int64
	if len(latest.Kvs) == 0 {
		targetKeyRevision = endRevision
	} else {
		targetKeyRevision = latest.Kvs[0].ModRevision
	}
	requestedStart := longOrNull(params, "startRevision")

View on GitHub (pinned to c0390bff16)

Solutions

  1. Re-run history without endRevision (or with a recent one) so the query anchors at the current revision.
  2. Increase etcd's --auto-compaction-retention to retain more history.
  3. Clamp startRevision to the compact revision reported; never query below it.
  4. Persist and use the revision reported in the error message as the new lower bound for future queries.

Example fix

// before
result, err := session.history(map[string]json.RawMessage{"endRevision": json.RawMessage("50")}) // compacted
// after
// omit stale endRevision, or use the reported compact revision + 1
result, err := session.history(map[string]json.RawMessage{})
Defensive patterns

Strategy: fallback

Validate before calling

compactRev := lastKnownCompactRevision() // track from prior ETCD_COMPACTED errors
if endRevision != nil && *endRevision <= compactRev {
	endRevision = nil // anchor at latest instead of a compacted revision
}

Try / catch

result, err := session.history(params)
if err != nil {
	if strings.HasPrefix(err.Error(), "ETCD_COMPACTED") {
		params = dropEndRevision(params) // fall back to latest-revision anchor
		result, err = session.history(params)
	}
	if err != nil { return nil, err }
}

Prevention

When it happens

Trigger: Calling history with endRevision older than the cluster's current compact revision, or with a very old default window (10000 revisions) on a cluster that compacts aggressively; the Get at that revision returns rpctypes.ErrCompacted.

Common situations: Replaying an old snapshot/audit query after the etcd server auto-compacted; long-lived clients with stale revision bookmarks; clusters with short --auto-compaction-retention and infrequent history queries.

Related errors


AI-assisted analysis of t8y2/dbx@c0390bff16 (2026-09-05). Data as JSON: /api/errors/59cb7561bfde6fc4. Report an issue: GitHub.