{"record":{"id":"0e395e1e0f26d699","repo":"thedotmack/claude-mem","slug":"projection-error-one-operation-exceeds-projection-request","errorCode":null,"errorMessage":"projection_error: one operation exceeds projection request byte budget","messagePattern":"projection_error: one operation exceeds projection request byte budget","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"workers/sync-hub/src/do/SyncHub.ts","lineNumber":715,"sourceCode":"\t\t\tprojected,\n\t\t\ttarget,\n\t\t\ttarget,\n\t\t\ttarget,\n\t\t\tlimit,\n\t\t).toArray();\n\t\tconst ops: ChangeOp[] = [];\n\t\tfor (const row of rows) {\n\t\t\tconst op = toChange(row);\n\t\t\tconst candidate = [...ops, op];\n\t\t\tconst bytes = projectionRequestBytes({\n\t\t\t\tuserId,\n\t\t\t\tepoch,\n\t\t\t\tfromSeqExclusive: projected,\n\t\t\t\tthroughSeq: op.seq,\n\t\t\t\tops: candidate,\n\t\t\t});\n\t\t\tif (bytes > byteLimit) {\n\t\t\t\tif (ops.length === 0) throw projectionError(\"one operation exceeds projection request byte budget\");\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tops.push(op);\n\t\t}\n\t\tif (ops.length === 0 && compareCanonicalDecimals(projected, target) < 0) {\n\t\t\tthrow projectionError(\"unprojected log gap\");\n\t\t}\n\t\tthis.renewProjectionLease(leaseToken, now);\n\t\treturn {\n\t\t\tprotocol_version: 1,\n\t\t\tepoch,\n\t\t\tfrom_seq_exclusive: projected,\n\t\t\tthrough_seq: ops.length > 0 ? ops[ops.length - 1].seq : projected,\n\t\t\ttarget_seq: target,\n\t\t\tops,\n\t\t};\n\t}\n","sourceCodeStart":697,"sourceCodeEnd":733,"githubUrl":"https://github.com/thedotmack/claude-mem/blob/d8bc9755e74915e5c3b999181e10a67c889bce2a/workers/sync-hub/src/do/SyncHub.ts#L697-L733","documentation":"getProjectionPage() batches ops subject to a byte budget (maxBytes, capped at PROJECTION_PAGE_MAX_BYTES). If a single serialized operation alone exceeds that budget — before any op has been accumulated — no valid page can be produced, so the DO throws this projectionError instead of returning an oversized request.","triggerScenarios":"Calling getProjectionPage with maxBytes set very low (e.g. 1 or a tiny value) while the log contains an op larger than that budget; or a single canonical op genuinely larger than PROJECTION_PAGE_MAX_BYTES.","commonSituations":"Operator passes maxBytes as a small number intending 'few ops' but the unit is bytes; a legitimately huge op (e.g. a large document mutation) landed in the log and now no projection page can pass over it with default limits.","solutions":["Raise maxBytes (and confirm it is bytes, not ops) so it comfortably exceeds the largest op in the range; the DO caps it at PROJECTION_PAGE_MAX_BYTES, so if the op exceeds the server cap the cap itself must be raised in config/code.","Increase PROJECTION_PAGE_MAX_OPS/PAGE byte constants in the hub if large ops are legitimate for your workload.","Split overly large client mutations at write time so no single canonical op exceeds the projection byte budget.","Catch this error and route the offending seq to a dead-letter/splitting path instead of retrying the same page forever."],"exampleFix":"// before\nconst page = hub.getProjectionPage(token, target, userId, 500, 1024);\n// after\nconst page = hub.getProjectionPage(token, target, userId, 500, PROJECTION_PAGE_MAX_BYTES);","handlingStrategy":"validation","validationCode":"const byteLimit = Math.min(requestedBytes, PROJECTION_PAGE_MAX_BYTES);\nif (largestKnownOpBytes > byteLimit) {\n  throw new Error(`op too large for projection budget: ${largestKnownOpBytes} > ${byteLimit}`);\n}","typeGuard":null,"tryCatchPattern":"try {\n  page = hub.getProjectionPage(token, target, userId, maxOps, maxBytes);\n} catch (e) {\n  if (String(e).includes('byte budget')) {\n    // raise maxBytes to server cap or split/skip the oversized op\n    page = hub.getProjectionPage(token, target, userId, maxOps, PROJECTION_PAGE_MAX_BYTES);\n  } else throw e;\n}","preventionTips":["Remember maxBytes is bytes, not op count","Cap client mutation sizes at write time below PROJECTION_PAGE_MAX_BYTES","Alert when a single op approaches the byte limit"],"tags":["projection","limits","payload-size"],"backgroundTag":"payload-too-large","analyzedSha":"d8bc9755e74915e5c3b999181e10a67c889bce2a","analyzedAt":"2026-09-17T16:40:26.182Z","contentChangedAt":"2026-09-17T16:40:26.182Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}