{"record":{"id":"29fd0ba4731b7b22","repo":"thedotmack/claude-mem","slug":"ops-index-error-instanceof-error-error-message-string-error","errorCode":null,"errorMessage":"ops[${index}] ${error instanceof Error ? error.message : String(error)}","messagePattern":"ops\\[\\$\\{index\\}\\] \\$\\{error instanceof Error \\? error\\.message : String\\(error\\)\\}","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"workers/sync-hub/src/do/SyncHub.ts","lineNumber":386,"sourceCode":"\n\t// ---------------------------------------------------------------------\n\t// Canonical append path and client cursor reads.\n\t// ---------------------------------------------------------------------\n\n\tasync pushOps(deviceId: string, ops: PushOp[], deviceName: string | null = null): Promise<PushOutcome> {\n\t\tlet rows: ValidatedOp[];\n\t\ttry {\n\t\t\tif (typeof deviceId !== \"string\" || deviceId.length === 0) throw invalid(\"deviceId must be non-empty\");\n\t\t\tif (!Array.isArray(ops)) throw invalid(\"ops must be an array\");\n\t\t\trows = await Promise.all(ops.map(async (op, index) => {\n\t\t\t\ttry {\n\t\t\t\t\tconst parsed = await parseCanonicalOperation(op);\n\t\t\t\t\tif (parsed.body.origin_device_id !== deviceId) {\n\t\t\t\t\t\tthrow new Error(\"origin_device_id does not match authenticated X-Device-Id\");\n\t\t\t\t\t}\n\t\t\t\t\treturn parsed;\n\t\t\t\t} catch (error) {\n\t\t\t\t\tthrow invalid(`ops[${index}] ${error instanceof Error ? error.message : String(error)}`);\n\t\t\t\t}\n\t\t\t}));\n\t\t} catch (error) {\n\t\t\tif (error instanceof Error && error.message.startsWith(INVALID_OPS_PREFIX)) {\n\t\t\t\treturn { refused: true, error: error.message };\n\t\t\t}\n\t\t\tif (isDeviceLimitError(error)) return { refused: true, error: DEVICE_LIMIT_ERROR };\n\t\t\tthrow error;\n\t\t}\n\n\t\tconst sql = this.ctx.storage.sql;\n\t\tconst now = Date.now();\n\t\tconst nowDecimal = String(now);\n\t\tconst headBefore = this.headSeq();\n\t\tconst acked: AckedOp[] = [];\n\t\ttry {\n\t\t\tthis.ctx.storage.transactionSync(() => {\n\t\t\t\tthis.touchDevice(deviceId, normalizeDeviceName(deviceName), now);","sourceCodeStart":368,"sourceCodeEnd":404,"githubUrl":"https://github.com/thedotmack/claude-mem/blob/d8bc9755e74915e5c3b999181e10a67c889bce2a/workers/sync-hub/src/do/SyncHub.ts#L368-L404","documentation":"Aggregated per-op validation failure in SyncHubDO.pushOps: while parsing/validating ops[index], parseCanonicalOperation or the origin_device_id match check failed, and the inner message is prefixed onto ops[index] to pinpoint the offending entry. The whole batch is refused with this message via INVALID_OPS_PREFIX.","triggerScenarios":"Any op in the batch fails schema parsing (bad kind, malformed body, invalid revision format) or its parsed.body.origin_device_id differs from the authenticated deviceId — commonly op #N where a batch mixes devices or contains a hand-crafted op.","commonSituations":"Merged/replayed batches after a client restore containing ops from an old device id, schema drift after a client upgrade introducing a new op kind the hub doesn't parse, corrupted local op queue.","solutions":["Read the index in ops[N] and the inner message to find the bad op","Ensure every op's origin_device_id equals the authenticated X-Device-Id","Drop or re-create the offending op client-side and re-push the rest","Upgrade/downgrade the client so its op schema matches the hub's parser"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"ops.forEach((op, i) => {\n  if (op.body?.origin_device_id !== deviceId) throw new Error(`op ${i} origin_device_id mismatch`);\n});","typeGuard":null,"tryCatchPattern":"try {\n  return await hub.push(deviceId, ops);\n} catch (e) {\n  const m = String(e).match(/ops\\[(\\d+)\\] (.+)/);\n  if (m) { dropOp(Number(m[1])); return retryPushWithoutBadOps(); }\n  throw e;\n}","preventionTips":["Stamp every op with the same device id used for authentication","Validate ops locally (schema + origin_device_id) before batching","Rebuild the local op queue after client restores or version upgrades"],"tags":["validation","sync","batch"],"backgroundTag":"schema-validation-failed","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"}