thedotmack/claude-mem · error
sync hub push: distinct operation tuples claimed the same se
Error message
sync hub push: distinct operation tuples claimed the same sequence
What it means
Thrown when two DISTINCT operation tuples (different operationTupleKey) are assigned the SAME `seq` by the hub. Each sequence number must belong to exactly one operation; a collision means the hub's sequencer is broken. Detected via the inverse seqTuple map (seq -> tuple).
Source
Thrown at src/services/sync/CloudSync.ts:1051
const ackCounts = new Map<string, number>();
const tupleSeq = new Map<string, string>();
const seqTuple = new Map<string, string>();
for (const ack of response.acked) {
const key = operationTupleKey(ack);
if (!sentCounts.has(key)) {
throw new Error('sync hub push: 200 response contains an extra or mismatched acknowledgment tuple');
}
ackCounts.set(key, (ackCounts.get(key) ?? 0) + 1);
const priorTupleSeq = tupleSeq.get(key);
if (priorTupleSeq !== undefined && priorTupleSeq !== ack.seq) {
throw new Error('sync hub push: duplicate operation tuple claimed different sequences');
}
tupleSeq.set(key, ack.seq);
const priorSeqTuple = seqTuple.get(ack.seq);
if (priorSeqTuple !== undefined && priorSeqTuple !== key) {
throw new Error('sync hub push: distinct operation tuples claimed the same sequence');
}
seqTuple.set(ack.seq, key);
}
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) {View on GitHub (pinned to d768ba3643)
Solutions
- Find the two acked entries sharing one seq but differing in tuple — that seq is the hub collision point.
- Fix the hub sequencer so seq allocation is unique and monotonic.
- Do not apply this batch; retry once the hub is corrected, since applying would corrupt local ordering.
- Inspect hub logs around the colliding seq for concurrent allocation.
Defensive patterns
Strategy: try-catch
Try / catch
try { await cloudSync.push(pushed); }
catch (e) {
if (e instanceof Error && e.message.includes('distinct operation tuples claimed the same sequence')) {
logger.error('SYNC', e.message); // hub seq collision; escalate
return;
}
throw e;
} Prevention
- Monitor hub responses for seq collisions; this indicates a sequencer allocation bug.
- Keep the client strict (do not relax this check) — applying colliding seqs corrupts local order.
- Attach the colliding seq and both tuples to incident reports.
When it happens
Trigger: A 200 push response where two acked entries have different (id, kind, entity_rev, operation_sha256) but identical `seq`. The first sets seqTuple[seq]=keyA; the second with a different key but same seq triggers the throw.
Common situations: Hub sequencer race/duplicate allocation, sequence reuse after a rollback, or a hub that sequences by a non-unique attribute. Pure hub-side integrity violation; the client correctly refuses to apply an ambiguous ordering.
Related errors
- sync hub push: duplicate operation tuple claimed different s
- sync hub push: acknowledgment seq exceeds head_seq
- sync hub push: sent operation is not covered by projected_se
- sync hub push: acked[${index}] must be an object
- sync hub push: malformed acked[${index}]
AI-assisted analysis of thedotmack/claude-mem@d768ba3643 (2026-08-12).
Data as JSON: /api/errors/d9657f0c6c43a206.
Report an issue: GitHub.