thedotmack/claude-mem · error
SyncApply: ops out of order (seq ${op.seq} after ${lastSeq})
Error message
SyncApply: ops out of order (seq ${op.seq} after ${lastSeq}) What it means
Thrown by SyncApply when an op's seq is <= lastSeq but > cursor — i.e. it is past the cursor (so not a replay-skip) yet not greater than the highest seq already seen in this same batch. Ops within a page must be strictly monotonically increasing; a duplicate or regression triggers this.
Source
Thrown at src/services/sync/SyncApply.ts:469
const cursor = this.getCursor();
let lastSeq = cursor;
for (const op of ops) {
const seq = assertCanonicalDecimal(op.seq, { positive: true });
assertCanonicalDecimal(op.rev, { positive: true });
// Strict HTTP pages describe the exact raw suffix after our cursor.
// Validate every supplied sequence before the ordinary replay skip;
// otherwise a stale prefix (even an out-of-order one) is silently
// discarded and a malformed page can look contiguous.
if (options.requireContiguous === true && seq !== incrementCanonicalDecimal(lastSeq)) {
throw new Error(`SyncApply: sequence gap (expected ${incrementCanonicalDecimal(lastSeq)}, got ${seq})`);
}
if (compareCanonicalDecimals(seq, cursor) <= 0) {
result.skippedCursor++;
continue;
}
if (compareCanonicalDecimals(seq, lastSeq) <= 0) {
throw new Error(`SyncApply: ops out of order (seq ${op.seq} after ${lastSeq})`);
}
lastSeq = seq;
if (op.origin_device === this.deviceId) {
result.skippedOwn++;
continue;
}
let outcome: 'applied' | 'stale';
if (op.kind === 'mutation') {
outcome = this.applyMutation(op);
} else {
outcome = this.applyCanonicalRowOp(op, chromaJobs);
}
if (outcome === 'applied') result.applied++;
else result.skippedStale++;
}
View on GitHub (pinned to d768ba3643)
Solutions
- Inspect the page for the seq that regressed relative to lastSeq (the message names both seq and lastSeq).
- Ensure the hub returns ops sorted by ascending seq within a page.
- Re-request the page from the current cursor; do not merge overlapping pages client-side.
- If duplicates are expected from the hub, dedup by seq before calling applyOps.
Defensive patterns
Strategy: validation
Validate before calling
// Pre-sort/dedup a page by seq before applying (only if hub ordering is unreliable):
function normalizePage(ops: SyncOp[]): SyncOp[] {
return ops
.filter((op, i, arr) => arr.findIndex(o => o.seq === op.seq) === i) // dedup by seq
.sort((a, b) => compareCanonicalDecimals(a.seq, b.seq));
} Try / catch
try { apply.applyOps(page, opts); }
catch (e) {
if (e instanceof Error && e.message.startsWith('SyncApply: ops out of order')) {
// hub returned non-monotonic page; sort+dedup then retry without strict contiguity
apply.applyOps(normalizePage(page), { requireContiguous: false }); return;
}
throw e;
} Prevention
- Expect the hub to return ops sorted by ascending seq; report if it does not.
- Do not stitch overlapping pages client-side — fetch each from the cursor.
- If duplicate seqs are expected, dedup before applyOps.
When it happens
Trigger: In applyOps, after the contiguous check: if compareCanonicalDecimals(seq, cursor) <= 0 it is skipped as already-applied; otherwise if compareCanonicalDecimals(seq, lastSeq) <= 0 it throws. Fires when a page contains a seq that goes backward relative to an earlier op in the same page (and is not behind the cursor).
Common situations: Hub returned a page with non-monotonic seq ordering, a duplicate op within one page, or a page stitched from two overlapping fetches. The contiguous check [131] only runs when requireContiguous is true, but this out-of-order check always runs, so it catches unordered pages even in non-strict mode.
Related errors
- SyncApply: sequence gap (expected ${incrementCanonicalDecima
- sync hub push: duplicate operation tuple claimed different s
- sync hub push: distinct operation tuples claimed the same se
- sync hub push: acknowledgment seq exceeds head_seq
- sync hub push: sent operation is not covered by projected_se
AI-assisted analysis of thedotmack/claude-mem@d768ba3643 (2026-08-12).
Data as JSON: /api/errors/9b68d43f0987777c.
Report an issue: GitHub.