thedotmack/claude-mem · error

sync hub push: sent operation is not covered by…

Error message

sync hub push: sent operation is not covered by projected_seq

What it means

An acked operation's seq exceeds the response's projected_seq — the acknowledgment is not covered by the projection checkpoint, breaking the core promise that 200 is returned only when the checkpoint covers every acknowledged commit. Caught in validatePushResponse before any local stamping; flush() backs off and retries the same ops (hub dedupe keeps this safe).

Solutions

  1. Check hub metrics/logs for projection lag at the time of the failure
  2. Restore the gate: the hub must not answer 200 until projected_seq >= every ack.seq it returns
  3. If projection advance is failing (worker crash, Pro errors), fix that root cause first
  4. Clients self-heal via retry once the hub honors the checkpoint gate again
Defensive patterns

Strategy: validation

Validate before calling

// Hub-side gate: 200 only when the checkpoint covers every ack:
function checkpointCoversAcks(acked: { seq: string }[], projected_seq: string): boolean {
  return acked.every(a => BigInt(a.seq) <= BigInt(projected_seq));
}
// if (!checkpointCoversAcks(...)) await waitForProjection(minAckSeq) before responding

Type guard

function acksCoveredByCheckpoint(acked: { seq: string }[], projected_seq: string): boolean {
  return acked.every(a => BigInt(a.seq) <= BigInt(projected_seq));
}

Try / catch

if (/not covered by projected_seq/.test(sync.status().lastError ?? '')) {
  // hub returned 200 too early: projection gate broken or projection worker failing; check hub logs
}

Prevention

When it happens

Trigger: Hub emits acks from the append path but projected_seq from a lagging projection worker; projection advance fails silently and the response path doesn't wait on it; field computation order bug in the response builder.

Common situations: Hub under heavy load where the projection falls behind and the 200 gate was relaxed; a hub change that made projection fire-and-forget; partial deployment mixing gated and ungated response paths.

Related errors


AI-assisted analysis of thedotmack/claude-mem@e2d1df569a (2026-08-20). Data as JSON: /api/errors/eb84ae8334d95a79. Report an issue: GitHub.

Appendix: source

Thrown at src/services/sync/CloudSync.ts:1077

        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.
   */
  private stampAcked(acked: AckedOp[], pushed: WireOp[]): void {
    const now = Date.now();
    const bodies = new Map(pushed.map(op => {
      const body = parseCanonicalOperation(op);
      return [operationTupleKey({
        id: body.id,
        kind: body.kind,
        entity_rev: body.entity_rev,
        operation_sha256: op.operation_sha256,
      }), { body, operationSha256: op.operation_sha256 }] as const;

View on GitHub (pinned to e2d1df569a)