{"record":{"id":"1a91cf808b2539ba","repo":"thedotmack/claude-mem","slug":"sync-hub-push-200-response-contains-an-extra-or-m","errorCode":null,"errorMessage":"sync hub push: 200 response contains an extra or mismatched acknowledgment tuple","messagePattern":"sync hub push: 200 response contains an extra or mismatched acknowledgment tuple","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/services/sync/CloudSync.ts","lineNumber":1039,"sourceCode":"    const sentCounts = new Map<string, number>();\n    for (const op of pushed) {\n      const body = parseCanonicalOperation(op);\n      const key = operationTupleKey({\n        id: body.id,\n        kind: body.kind,\n        entity_rev: body.entity_rev,\n        operation_sha256: op.operation_sha256,\n      });\n      sentCounts.set(key, (sentCounts.get(key) ?? 0) + 1);\n    }\n\n    const ackCounts = new Map<string, number>();\n    const tupleSeq = new Map<string, string>();\n    const seqTuple = new Map<string, string>();\n    for (const ack of response.acked) {\n      const key = operationTupleKey(ack);\n      if (!sentCounts.has(key)) {\n        throw new Error('sync hub push: 200 response contains an extra or mismatched acknowledgment tuple');\n      }\n      ackCounts.set(key, (ackCounts.get(key) ?? 0) + 1);\n\n      const priorTupleSeq = tupleSeq.get(key);\n      if (priorTupleSeq !== undefined && priorTupleSeq !== ack.seq) {\n        throw new Error('sync hub push: duplicate operation tuple claimed different sequences');\n      }\n      tupleSeq.set(key, ack.seq);\n\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;","sourceCodeStart":1021,"sourceCodeEnd":1057,"githubUrl":"https://github.com/thedotmack/claude-mem/blob/e2d1df569a8f04075d40e92461128ece7cf04c82/src/services/sync/CloudSync.ts#L1021-L1057","documentation":"validatePushResponse() builds the exact multiset of sent (id, kind, entity_rev, operation_sha256) tuples and rejects any acked tuple that was not in the request. The hub must acknowledge exactly what was pushed — an extra or unknown tuple means the response belongs to a different request or was fabricated. The check runs before any SQLite mutation (stampAcked), so local state is safe; flush() backs off and retries, and hub dedupe makes re-pushes harmless. Treat persistent occurrences as a hub integrity or routing problem.","triggerScenarios":"Hub acks ops from a previous batch (cross-request state bleed); load-balanced hub replicas with divergent logs returning each other's acknowledgments; a proxy cache replaying an old 200 body; a hub bug echoing expected acks derived from something other than the appended ops.","commonSituations":"Sticky-session-less LB over hub replicas that don't share a single durable log; an intermediary caching POST responses (RFC violation but it happens); hub mid-incident returning stale responses.","solutions":["Log the pushed tuple keys next to the acked ones to identify what the hub returned that was never sent","Verify all hub replicas share one authoritative log — no per-replica append paths behind a load balancer","Disable POST caching at every intermediary in front of the hub","Upgrade/patch the hub if its ack derivation diverges from the appended ops","Last resort: the local queue can be re-drained from scratch for the affected entities; hub dedupe on (origin_device, kind, origin_id, rev) makes the re-push safe"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// You cannot pre-validate a remote hub's behavior; pre-compute your sent tuple set\n// so you can diff against the hub response when investigating:\nconst sentKeys = new Set(ops.map(op => {\n  const body = parseCanonicalOperation(op);\n  return JSON.stringify([body.id, body.kind, body.entity_rev, op.operation_sha256]);\n}));\n// on failure, diff response.acked keys against sentKeys to see the phantom tuple","typeGuard":null,"tryCatchPattern":"if (/extra or mismatched acknowledgment tuple/.test(sync.status().lastError ?? '')) {\n  // hub integrity/routing alert: verify single durable log behind the LB,\n  // disable POST caching at intermediaries, then let the backoff retry\n}","preventionTips":["Run the hub as one authoritative log (or a single-writer sequencer) behind any load balancer","Disable caching of POST at every CDN/proxy in front of the hub","Alert on this message — it should be impossible in a healthy deployment"],"tags":["sync","hub","integrity","ack","invariant"],"backgroundTag":"data-integrity-violation","analyzedSha":"e2d1df569a8f04075d40e92461128ece7cf04c82","analyzedAt":"2026-08-20T23:58:13.836Z","contentChangedAt":"2026-08-20T23:58:13.836Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}