thedotmack/claude-mem · error
sync hub push: distinct operation tuples claimed the same…
Error message
sync hub push: distinct operation tuples claimed the same sequence
What it means
Two distinct acked tuples claim the same seq — the hub handed one log sequence number to two different operations. Sequence ownership must be unique (one seq ↔ one op); this check, together with the tuple→seq check, proves the bijective mapping before anything is stamped. Caught pre-stamp in validatePushResponse; flush() backs off and retries. Indicates a hub sequence-allocation bug or replica divergence.
Solutions
- Inspect the hub log around the reported seq for double-assigned entries
- Make sequence allocation single-writer/atomic (transactional autoincrement on the authoritative log)
- If replicas append in parallel, route all appends through one sequencer before fan-out
- Repair or re-sequence the affected log segment, then let clients re-converge via retry
Defensive patterns
Strategy: try-catch
Try / catch
if (/distinct operation tuples claimed the same sequence/.test(sync.status().lastError ?? '')) {
// seq double-allocation on the hub: inspect the log around that seq, fix the sequencer
} Prevention
- Allocate sequence numbers from a single-writer atomic source (autoincrement on the authoritative log)
- Never allow parallel replicas to assign seqs independently
- Hub CI: concurrency test asserting unique seq ownership across parallel appends
When it happens
Trigger: Hub allocates seqs with a non-atomic counter under concurrent appends; two replicas independently assigned the same seq after a partition; a rebuild/replay of the hub log reused sequence numbers.
Common situations: Hub concurrency regression after a performance refactor; multi-writer hub topology introduced without single-writer sequencing; log replay tooling reusing seqs.
Related errors
- sync hub push: acknowledgment seq exceeds head_seq
- sync hub push: checkpoint order requires head_seq <=…
- sync hub push: 200 response acknowledgment multiplicity…
- sync hub push: 200 response contains an extra or mismatched…
- sync hub push: duplicate operation tuple claimed different…
AI-assisted analysis of thedotmack/claude-mem@e2d1df569a (2026-08-20).
Data as JSON: /api/errors/d9657f0c6c43a206.
Report an issue: GitHub.
Appendix: 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 e2d1df569a)