{"record":{"id":"812425646b35a386","repo":"thedotmack/claude-mem","slug":"syncapply-invalid-op-seq-op-seq-kind-op-kind-origin-op-812425","errorCode":null,"errorMessage":"SyncApply: invalid op seq=${op.seq} kind=${op.kind} origin=${op.origin_device}/${op.origin_id}: unknown row kind","messagePattern":"SyncApply: invalid op seq=(.+?) kind=(.+?) origin=(.+?)/(.+?): unknown row kind","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/services/sync/SyncApply.ts","lineNumber":600,"sourceCode":"        updated_at_epoch=excluded.updated_at_epoch\n    `).run(\n      op.entity_id, op.kind, op.origin_device, op.origin_id, op.entity_rev,\n      op.operation_sha256, op.deleted === true ? 1 : 0, this.now(),\n    );\n    return outcome;\n  }\n\n  private applyRowOp(op: SyncOp, chromaJobs: ChromaJob[]): 'applied' | 'stale' {\n    const body = this.parseBody(op);\n    switch (op.kind) {\n      case 'observation':\n        return this.applyObservation(op, body, chromaJobs);\n      case 'summary':\n        return this.applySummary(op, body, chromaJobs);\n      case 'prompt':\n        return this.applyPrompt(op, body, chromaJobs);\n      default:\n        throw invalidOp(op, `unknown row kind`);\n    }\n  }\n\n  // ------------------------------------------------------------------------\n  // Title parking (see SET_TITLE CONVERGENCE in the module header)\n  // ------------------------------------------------------------------------\n\n  private static parkedTitleMemKey(memorySessionId: string): string {\n    return `parked_title:mem:${memorySessionId}`;\n  }\n\n  private static parkedTitleContentKey(platform: string, contentSessionId: string): string {\n    return `parked_title:content:${platform}:${contentSessionId}`;\n  }\n\n  private parkTitle(key: string, title: string): void {\n    // Last parked title for an identity wins (log order — a later set_title\n    // in the same replay overwrites the earlier one).","sourceCodeStart":582,"sourceCodeEnd":618,"githubUrl":"https://github.com/thedotmack/claude-mem/blob/d8bc9755e74915e5c3b999181e10a67c889bce2a/src/services/sync/SyncApply.ts#L582-L618","documentation":"applyRowOp dispatches on the op's row kind (session/observation/summary/prompt). Any other kind string hits the default branch and is rejected. This guards against typos and unknown kinds from newer producers whose kinds the current applier cannot map to a table.","triggerScenarios":"op.kind is misspelled (e.g. 'obsrvation', 'summaries'), a newer producer version introduced a row kind this build doesn't know, or the kind field was set to null/undefined and stringified oddly.","commonSituations":"Version skew: a device upgraded to a schema that adds a new row kind syncs to an older node; a hand-written migration tool emitted an ad-hoc kind; a case-sensitivity bug ('Summary' vs 'summary').","solutions":["Check op.kind for seq=${op.seq}; fix the producer to use one of the supported kinds (session/observation/summary/prompt as dispatched in applyRowOp).","Upgrade this node to a build that recognizes the new kind if a newer producer introduced it.","Hold back ops of unknown kinds until all nodes are upgraded, or drop and re-create them with a supported kind.","Normalize kind casing on the producer to lowercase exactly as the applier expects."],"exampleFix":"// before\n{ kind: 'Summary', ... }\n// after\n{ kind: 'summary', ... }","handlingStrategy":"validation","validationCode":"const ROW_KINDS = ['session','observation','summary','prompt'];\nif (!ROW_KINDS.includes(op.kind)) throw new Error(`unsupported kind: ${op.kind}`);","typeGuard":"const isKnownRowKind = (k) => ['session','observation','summary','prompt'].includes(k);","tryCatchPattern":"try {\n  applySyncOp(op);\n} catch (e) {\n  if (String(e.message).includes('unknown row kind')) {\n    logger.warn({ seq: op.seq, kind: op.kind }, 'unknown kind — hold until upgrade');\n    holdQueue.push(op);\n  } else throw e;\n}","preventionTips":["Centralize the kind constant list and import it on both producer and applier","Keep kinds lowercase and exact; validate at enqueue time","Upgrade all nodes before a producer starts emitting new row kinds"],"tags":["sync","enum","dispatch"],"backgroundTag":"invalid-enum-value","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"}