{"record":{"id":"4c7b398d91f3eaa9","repo":"thedotmack/claude-mem","slug":"syncapply-invalid-op-seq-op-seq-kind-op-kind-origin-op-4c7b39","errorCode":null,"errorMessage":"SyncApply: invalid op seq=${op.seq} kind=${op.kind} origin=${op.origin_device}/${op.origin_id}: unknown mutation op ${String(body.op)}","messagePattern":"SyncApply: invalid op seq=(.+?) kind=(.+?) origin=(.+?)/(.+?): unknown mutation op (.+?)","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/services/sync/SyncApply.ts","lineNumber":957,"sourceCode":"    return 'applied';\n  }\n\n  // -------------------------------------------------------------------------\n  // Mutation ops\n  // -------------------------------------------------------------------------\n\n  private applyMutation(op: SyncOp): 'applied' | 'stale' {\n    const body = this.parseBody(op);\n    const mutationOp = fieldString(op, body, 'op');\n    switch (mutationOp) {\n      case 'set_title':\n        return this.applySetTitle(op, body);\n      case 'set_prompt_session':\n        return this.applySetPromptSession(op, body);\n      case 'remap_project':\n        return this.applyRemapProject(op, body);\n      default:\n        throw invalidOp(op, `unknown mutation op ${String(body.op)}`);\n    }\n  }\n\n  /**\n   * set_title resolution (three steps — see SET_TITLE CONVERGENCE in the\n   * module header): direct session match → via a replicated prompt's content\n   * id → park in sync_state for a later claim. sdk_sessions carries no\n   * sync_rev (v41 touches only the synced tables), so rev is never\n   * consulted: direct applications overwrite in hub-log order; parked\n   * claims fill only a NULL custom_title.\n   */\n  private applySetTitle(op: SyncOp, body: Record<string, unknown>): 'applied' | 'stale' {\n    const target = body.target as Record<string, unknown> | undefined;\n    const fields = body.fields as Record<string, unknown> | undefined;\n    if (!target || typeof target !== 'object' || Array.isArray(target) || !fields || typeof fields !== 'object' || Array.isArray(fields)) {\n      throw invalidOp(op, 'set_title requires target and fields objects');\n    }\n    const customTitle = fieldString(op, fields, 'custom_title');","sourceCodeStart":939,"sourceCodeEnd":975,"githubUrl":"https://github.com/thedotmack/claude-mem/blob/d8bc9755e74915e5c3b999181e10a67c889bce2a/src/services/sync/SyncApply.ts#L939-L975","documentation":"applyMutation dispatches on body.op for mutation ops (set_title, set_prompt_session, remap_project, ...). An unrecognized body.op means the producer is either buggy or from a newer version with mutations this applier can't execute. Rejecting avoids silently ignoring a mutation and diverging replicas.","triggerScenarios":"A mutation op body has an op field with an unknown/misspelled value (e.g. 'rename_title' instead of 'set_title'), op is undefined, or a newer producer version introduced a mutation kind this build predates.","commonSituations":"Version skew after an upgrade that added a new mutation type; a typo in the producer's mutation constant; a refactor renamed mutation ops without a compatibility shim for in-flight queued ops.","solutions":["Inspect body.op for seq=${op.seq}; correct the producer to emit one of the supported mutation ops (set_title, set_prompt_session, remap_project, etc.).","Upgrade this node to a version that recognizes the new mutation op if it was introduced by a newer producer.","Add an explicit migration for in-flight ops when renaming a mutation kind: rewrite queued rows to the new op name before deploying.","Fail fast on the producer: validate the op name against the supported set at enqueue time."],"exampleFix":"// before\nbody: { op: 'rename_title', ... }\n// after\nbody: { op: 'set_title', ... }","handlingStrategy":"try-catch","validationCode":"const MUTATION_OPS = ['set_title','set_prompt_session','remap_project'];\nif (!MUTATION_OPS.includes(body.op)) throw new Error(`unsupported mutation: ${body.op}`);","typeGuard":"const isKnownMutationOp = (op) => ['set_title','set_prompt_session','remap_project'].includes(op);","tryCatchPattern":"try {\n  applySyncOp(op);\n} catch (e) {\n  if (String(e.message).includes('unknown mutation op')) {\n    logger.warn({ seq: op.seq, mutation: body.op }, 'unknown mutation — upgrade required');\n    holdQueue.push(op);\n  } else throw e;\n}","preventionTips":["Share the mutation-op constant list between producer and applier","Validate the mutation name at enqueue time on the producer","When renaming a mutation op, migrate queued rows before deploying"],"tags":["sync","enum","mutation","version-skew"],"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"}