{"record":{"id":"e815fad7a4d34652","repo":"thedotmack/claude-mem","slug":"sync-hub-push-200-response-acknowledgment-multise","errorCode":null,"errorMessage":"sync hub push: 200 response acknowledgment multiset mismatch","messagePattern":"sync hub push: 200 response acknowledgment multiset mismatch","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/services/sync/CloudSync.ts","lineNumber":1066,"sourceCode":"\n      const priorSeqTuple = seqTuple.get(ack.seq);\n      if (priorSeqTuple !== undefined && priorSeqTuple !== key) {\n        throw new Error('sync hub push: distinct operation tuples claimed the same sequence');\n      }\n      seqTuple.set(ack.seq, key);\n    }\n\n    for (const [key, expected] of sentCounts) {\n      const actual = ackCounts.get(key) ?? 0;\n      if (actual !== expected) {\n        throw new Error(\n          `sync hub push: 200 response acknowledgment multiplicity mismatch (expected ${expected}, received ${actual})`\n        );\n      }\n    }\n    if (ackCounts.size !== sentCounts.size) {\n      // Defensive: the unknown-tuple branch above should make this impossible.\n      throw new Error('sync hub push: 200 response acknowledgment multiset mismatch');\n    }\n\n    if (compareCanonicalDecimals(response.head_seq, response.projected_seq) > 0) {\n      throw new Error('sync hub push: checkpoint order requires head_seq <= projected_seq');\n    }\n    for (const ack of response.acked) {\n      if (compareCanonicalDecimals(ack.seq, response.head_seq) > 0) {\n        throw new Error('sync hub push: acknowledgment seq exceeds head_seq');\n      }\n      if (compareCanonicalDecimals(ack.seq, response.projected_seq) > 0) {\n        throw new Error('sync hub push: sent operation is not covered by projected_seq');\n      }\n    }\n  }\n\n  /**\n   * Stamp rows / delete outbox entries for a fully validated acknowledgment\n   * multiset. The hub may return entries in any order.","sourceCodeStart":1048,"sourceCodeEnd":1084,"githubUrl":"https://github.com/thedotmack/claude-mem/blob/d768ba364302d12b76e69e4f021f0bb1d2d50ed6/src/services/sync/CloudSync.ts#L1048-L1084","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try { await cloudSync.push(pushed); }\ncatch (e) {\n  if (e instanceof Error && e.message.includes('acknowledgment multiset mismatch')) {\n    // source says this is unreachable — file a bug with full acked array attached\n    logger.error('SYNC', 'unreachable multiset branch hit', {}, e); return;\n  }\n  throw e;\n}","preventionTips":["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."],"tags":["sync","cloud-sync","hub-response","validation","defensive","unreachable"],"backgroundTag":null,"analyzedSha":"d768ba364302d12b76e69e4f021f0bb1d2d50ed6","analyzedAt":"2026-08-12T23:52:55.241Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}