{"record":{"id":"60ec1ff581ef1cda","repo":"thedotmack/claude-mem","slug":"sync-hub-push-acknowledgment-seq-exceeds-head-seq","errorCode":null,"errorMessage":"sync hub push: acknowledgment seq exceeds head_seq","messagePattern":"sync hub push: acknowledgment seq exceeds head_seq","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/services/sync/CloudSync.ts","lineNumber":1074,"sourceCode":"    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.\n   */\n  private stampAcked(acked: AckedOp[], pushed: WireOp[]): void {\n    const now = Date.now();\n    const bodies = new Map(pushed.map(op => {\n      const body = parseCanonicalOperation(op);\n      return [operationTupleKey({\n        id: body.id,\n        kind: body.kind,","sourceCodeStart":1056,"sourceCodeEnd":1092,"githubUrl":"https://github.com/thedotmack/claude-mem/blob/d768ba364302d12b76e69e4f021f0bb1d2d50ed6/src/services/sync/CloudSync.ts#L1056-L1092","documentation":"Thrown when an acked operation's seq is greater than head_seq. An ack sequence cannot exceed the durable head — if the hub acked it, it must be at or below head_seq. This guards against the hub claiming a sequence it has not durably committed.","triggerScenarios":"validatePushResponse loops response.acked and runs compareCanonicalDecimals(ack.seq, response.head_seq); any ack with seq > head_seq throws. Runs after the checkpoint-order check [127] and before the projected_seq coverage check [129].","commonSituations":"Hub returned an ack with a seq beyond its own reported head (sequencer/head skew), head_seq was stale/under-reported in the same response, or a hub bug assigning seqs past the committed head. The local client correctly rejects an ack it cannot trust as durable.","solutions":["Identify the ack whose seq exceeds head_seq (loop response.acked comparing each seq to head_seq).","On the hub, ensure head_seq is advanced to at least the maximum acked seq before responding.","Retry after the hub fix; do not stamp outbox entries for seqs above head.","Check whether head_seq in the response was computed before the acks were sequenced (ordering bug)."],"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 seq exceeds head_seq')) {\n    logger.error('SYNC', e.message); // ack past durable head\n    return;\n  }\n  throw e;\n}","preventionTips":["Ensure the hub advances head_seq to >= max(acked seq) before responding.","Do not stamp outbox entries for seqs above head — they are not yet durable.","Alert when ack seqs exceed head; it signals a hub commit-ordering bug."],"tags":["sync","cloud-sync","hub-response","validation","checkpoint","sequence-integrity"],"backgroundTag":null,"analyzedSha":"d768ba364302d12b76e69e4f021f0bb1d2d50ed6","analyzedAt":"2026-08-12T23:52:55.241Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}