thedotmack/claude-mem · error
sync hub push: 200 response acknowledgment multiset mismatch
Error message
sync hub push: 200 response acknowledgment multiset mismatch
What it means
Defensive check: the number of distinct acked tuple keys (ackCounts.size) differs from the number of distinct sent tuple keys (sentCounts.size). The comment in source notes the unknown-tuple branch [122] should already make this unreachable — firing it indicates the earlier per-tuple checks were bypassed or a logic regression.
Source
Thrown at src/services/sync/CloudSync.ts:1066
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) {
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.View on GitHub (pinned to d768ba3643)
Solutions
- Treat as a code-regression signal: file a bug — the source comment states this branch should be unreachable.
- Verify operationTupleKey (JSON.stringify of [id, kind, entity_rev, operation_sha256]) has no collision for the current data; identical components collapse to one key.
- Diff validatePushResponse against the last known-good version to find loop/ordering changes.
- Add an assertion log of both map sizes and contents to capture how the invariant broke.
Defensive patterns
Strategy: try-catch
Try / catch
try { await cloudSync.push(pushed); }
catch (e) {
if (e instanceof Error && e.message.includes('acknowledgment multiset mismatch')) {
// source says this is unreachable — file a bug with full acked array attached
logger.error('SYNC', 'unreachable multiset branch hit', {}, e); return;
}
throw e;
} Prevention
- Treat as a regression: diff validatePushResponse against the last known-good revision.
- Never modify operationTupleKey's components without regenerating the multiset tests.
- Add a regression test asserting sentCounts.size === ackCounts.size after a known-good response.
When it happens
Trigger: validatePushResponse after the per-tuple multiplicity loop, if ackCounts.size !== sentCounts.size. Under the current control flow this should be impossible because any unknown ack throws at [122] first; reaching here implies a code regression or concurrent mutation of the maps.
Common situations: A refactored validatePushResponse that changed loop ordering, a Map key collision (e.g. operationTupleKey producing equal strings for distinct tuples), or non-deterministic iteration. Treat as a bug report, not a config issue.
Related errors
- sync hub push: acked[${index}] must be an object
- sync hub push: malformed acked[${index}]
- sync hub push: 200 response contains an extra or mismatched
- sync hub push: duplicate operation tuple claimed different s
- sync hub push: distinct operation tuples claimed the same se
AI-assisted analysis of thedotmack/claude-mem@d768ba3643 (2026-08-12).
Data as JSON: /api/errors/e815fad7a4d34652.
Report an issue: GitHub.