thedotmack/claude-mem · error
sync hub push: acknowledgment seq exceeds head_seq
Error message
sync hub push: acknowledgment seq exceeds head_seq
What it means
Thrown when an acked operation's seq is greater than head_seq. An ack sequence cannot exceed the durable head — if the hub acked it, it must be at or below head_seq. This guards against the hub claiming a sequence it has not durably committed.
Source
Thrown at src/services/sync/CloudSync.ts:1074
for (const [key, expected] of sentCounts) {
const actual = ackCounts.get(key) ?? 0;
if (actual !== expected) {
throw new Error(
`sync hub push: 200 response acknowledgment multiplicity mismatch (expected ${expected}, received ${actual})`
);
}
}
if (ackCounts.size !== sentCounts.size) {
// Defensive: the unknown-tuple branch above should make this impossible.
throw new Error('sync hub push: 200 response acknowledgment multiset mismatch');
}
if (compareCanonicalDecimals(response.head_seq, response.projected_seq) > 0) {
throw new Error('sync hub push: checkpoint order requires head_seq <= projected_seq');
}
for (const ack of response.acked) {
if (compareCanonicalDecimals(ack.seq, response.head_seq) > 0) {
throw new Error('sync hub push: acknowledgment seq exceeds head_seq');
}
if (compareCanonicalDecimals(ack.seq, response.projected_seq) > 0) {
throw new Error('sync hub push: sent operation is not covered by projected_seq');
}
}
}
/**
* Stamp rows / delete outbox entries for a fully validated acknowledgment
* multiset. The hub may return entries in any order.
*/
private stampAcked(acked: AckedOp[], pushed: WireOp[]): void {
const now = Date.now();
const bodies = new Map(pushed.map(op => {
const body = parseCanonicalOperation(op);
return [operationTupleKey({
id: body.id,
kind: body.kind,View on GitHub (pinned to d768ba3643)
Solutions
- Identify the ack whose seq exceeds head_seq (loop response.acked comparing each seq to head_seq).
- On the hub, ensure head_seq is advanced to at least the maximum acked seq before responding.
- Retry after the hub fix; do not stamp outbox entries for seqs above head.
- Check whether head_seq in the response was computed before the acks were sequenced (ordering bug).
Defensive patterns
Strategy: try-catch
Try / catch
try { await cloudSync.push(pushed); }
catch (e) {
if (e instanceof Error && e.message.includes('acknowledgment seq exceeds head_seq')) {
logger.error('SYNC', e.message); // ack past durable head
return;
}
throw e;
} Prevention
- Ensure the hub advances head_seq to >= max(acked seq) before responding.
- Do not stamp outbox entries for seqs above head — they are not yet durable.
- Alert when ack seqs exceed head; it signals a hub commit-ordering bug.
When it happens
Trigger: validatePushResponse loops response.acked and runs compareCanonicalDecimals(ack.seq, response.head_seq); any ack with seq > head_seq throws. Runs after the checkpoint-order check [127] and before the projected_seq coverage check [129].
Common situations: Hub returned an ack with a seq beyond its own reported head (sequencer/head skew), head_seq was stale/under-reported in the same response, or a hub bug assigning seqs past the committed head. The local client correctly rejects an ack it cannot trust as durable.
Related errors
- sync hub push: sent operation is not covered by projected_se
- sync hub push: duplicate operation tuple claimed different s
- sync hub push: distinct operation tuples claimed the same se
- sync hub push: checkpoint order requires head_seq <= project
- sync hub push: acked[${index}] must be an object
AI-assisted analysis of thedotmack/claude-mem@d768ba3643 (2026-08-12).
Data as JSON: /api/errors/60ec1ff581ef1cda.
Report an issue: GitHub.