{"record":{"id":"d43a6e0ec37a0937","repo":"affaan-m/ECC","slug":"missing-merge-payload-for-operation-destinationpath","errorCode":null,"errorMessage":"Missing merge payload for ${operation.destinationPath}","messagePattern":"Missing merge payload for (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"scripts/lib/install/apply.js","lineNumber":536,"sourceCode":"          }\n          return merged;\n        }, {\n          lockHeld: settingsLockHeld,\n          beforeCommit() {\n            assertSafeInstallOperation(appliedPlan, operation);\n          },\n        });\n        writtenDestinations.add(operation.destinationPath);\n        if (operation.kind === 'remove-claude-settings-hooks') {\n          completedHookRemovalCount += 1;\n        }\n        continue;\n      }\n\n      if (operation.kind === 'merge-json') {\n        const payload = cloneJsonValue(operation.mergePayload);\n        if (payload === undefined) {\n          throw new Error(`Missing merge payload for ${operation.destinationPath}`);\n        }\n\n        const filteredPayload = (\n          isMcpConfigPath(operation.destinationPath) && disabledServers.length > 0\n        )\n          ? filterMcpConfig(payload, disabledServers).config\n          : payload;\n\n        const currentValue = readOptionalJsonObject(\n          operation.destinationPath,\n          'existing JSON config'\n        );\n        const mergedValue = deepMergeJson(currentValue, filteredPayload);\n        fs.writeFileSync(operation.destinationPath, formatJson(mergedValue), 'utf8');\n        writtenDestinations.add(operation.destinationPath);\n        continue;\n      }\n","sourceCodeStart":518,"sourceCodeEnd":554,"githubUrl":"https://github.com/affaan-m/ECC/blob/8321021c54d670126ce3b2969d5deb880b4b0c2a/scripts/lib/install/apply.js#L518-L554","documentation":"For a 'merge-json' operation, applyInstallPlanLocked clones the operation's mergePayload; if the payload is undefined (cloneJsonValue returns undefined only for an undefined input), the plan is malformed and the apply aborts. A merge operation without a payload cannot be applied, so the library fails fast instead of writing a no-op.","triggerScenarios":"An install plan contains a merge-json operation whose mergePayload field is missing or explicitly undefined when applyInstallPlan runs — e.g. a programmatically constructed plan omitted the payload, or an older/newer plan format dropped it.","commonSituations":"Custom tooling generating install plans by hand; version skew between a plan file produced by one ECC version and applied by another; serialization dropping undefined payload fields.","solutions":["Regenerate the install plan so every merge-json operation carries a defined mergePayload.","If building plans in code, set mergePayload (even to an empty object {}) instead of leaving it undefined.","Upgrade/downgrade so the plan producer and applyInstallPlanLocked are the same ECC version."],"exampleFix":"// before\n{ kind: 'merge-json', destinationPath: settingsPath }\n// after\n{ kind: 'merge-json', destinationPath: settingsPath, mergePayload: { hooks: {} } }","handlingStrategy":"type-guard","validationCode":"// validate a plan before applying\nfor (const op of plan.operations) {\n  if (op.kind === 'merge-json' && op.mergePayload === undefined) {\n    throw new Error(`merge-json op for ${op.destinationPath} lacks mergePayload`);\n  }\n}","typeGuard":"const hasPayload = (op) => op.kind !== 'merge-json' || (op.mergePayload !== undefined && typeof op.mergePayload === 'object');","tryCatchPattern":"try {\n  await applyInstallPlan(plan);\n} catch (e) {\n  if (e.message.startsWith('Missing merge payload')) {\n    plan = regeneratePlan(); // rebuild with payloads\n    await applyInstallPlan(plan);\n  } else throw e;\n}","preventionTips":["Always construct merge-json operations with an explicit mergePayload.","Keep plan producer and ECC apply code on the same version.","Avoid JSON round-trips that drop undefined payload fields."],"tags":["installer","plan","internal-invariant","json"],"backgroundTag":"internal-invariant-violation","analyzedSha":"8321021c54d670126ce3b2969d5deb880b4b0c2a","analyzedAt":"2026-09-16T10:08:13.343Z","contentChangedAt":"2026-09-16T10:08:13.343Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}