t8y2/dbx · error
ETCD_HISTORY_FAILED
ETCD_HISTORY_FAILED
Error message
ETCD_HISTORY_FAILED:
What it means
Generic wrapper for any history-walk failure that is not ErrCompacted. In the history operation, if the retry loop records a historyFailure, the driver returns 'ETCD_HISTORY_FAILED: <underlying error>' at history.go:201, propagating the raw etcd clientv3 error text after the prefix. It means the incremental revision walk over the key's revisions failed server-side or on the wire.
Source
Thrown at agents/drivers/etcd-go/history.go:201
_ = client.RequestProgress(progressCtx)
progressCancel()
select {
case <-completed:
case <-time.After(15 * time.Second):
return nil, errors.New("ETCD_HISTORY_TIMEOUT: history replay did not reach the requested revision")
}
failureMu.Lock()
historyFailure := failure
failureMu.Unlock()
if historyFailure != nil {
if errors.Is(historyFailure, 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, errors.New("ETCD_HISTORY_FAILED: " + historyFailure.Error())
}
collector.mu.Lock()
rows := make([]map[string]any, len(collector.rows))
copy(rows, collector.rows)
truncated := collector.truncated
collector.mu.Unlock()
sort.SliceStable(rows, func(i, j int) bool {
a, _ := strconv.ParseInt(rows[i]["revision"].(string), 10, 64)
b, _ := strconv.ParseInt(rows[j]["revision"].(string), 10, 64)
return a > b
})
serialized := make([]any, len(rows))
for i, row := range rows {
serialized[i] = row
}
return map[string]any{
"events": serialized,View on GitHub (pinned to c0390bff16)
Solutions
- Read the text after the 'ETCD_HISTORY_FAILED: ' prefix to identify the underlying etcd error and apply that error's own remedy.
- Retry the history call — transient Unavailable/deadline failures often clear once the etcd member recovers.
- Check etcd cluster health (etcdctl endpoint health) and network connectivity to the member.
- Verify the client's RBAC role permits reading the key range.
- Increase the driver's rpc timeout or lower the history limit to shrink the walk.
Example fix
// before
const rows = history(session, key); // fails opaque 'ETCD_HISTORY_FAILED: ...'
// after
try { const rows = history(session, key, { limit: 50 }); }
catch (e) {
if (String(e).startsWith('ETCD_HISTORY_FAILED:')) retryWithBackoff();
else throw e;
} Defensive patterns
Strategy: retry
Validate before calling
const healthy = await checkClusterHealth(); // etcdctl endpoint health equivalent
if (!healthy) throw new Error('etcd cluster unhealthy; aborting history query'); Type guard
function isHistoryFailedError(e) { return String(e && e.message || e).startsWith('ETCD_HISTORY_FAILED:'); } Try / catch
try { return history(session, key, { limit: 100 }); }
catch (e) {
if (isHistoryFailedError(e) && isTransient(String(e).split('ETCD_HISTORY_FAILED: ')[1]))
return retryWithBackoff(() => history(session, key));
throw e;
} Prevention
- Monitor etcd member health and alert on Unavailable spikes.
- Keep history limit modest (<= 500) so walks finish within the RPC timeout.
- Verify RBAC read permissions for the keys you query.
- Handle the underlying error embedded after the prefix rather than the wrapper generically.
When it happens
Trigger: Calling the history operation when an underlying Get/revision-walk fails with a non-compaction etcd error: e.g. ErrGRPCUnavailable (server down), context deadline exceeded (rpcTimeoutSeconds), ErrGRPCPermissionDenied, or a transient gRPC stream failure mid-walk.
Common situations: etcd node being restarted or unreachable under load; network partition between driver and cluster; RBAC user lacking read permission on the key; request exceeding the driver's per-RPC timeout on very long history walks.
Related errors
- ETCD_COMPACTED
- Key is required
- unknown method: %s
- Unknown method: " + method
- DBX MCP tool failed: ${tool.name}
AI-assisted analysis of t8y2/dbx@c0390bff16 (2026-09-05).
Data as JSON: /api/errors/f874f0f458cd437d.
Report an issue: GitHub.