{"record":{"id":"e910af82bc98bbbc","repo":"affaan-m/ECC","slug":"a-managed-install-plan-with-operations-is-required","errorCode":null,"errorMessage":"A managed install plan with operations is required.","messagePattern":"A managed install plan with operations is required\\.","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"scripts/lib/multi-harness-setup.js","lineNumber":345,"sourceCode":"    requirements.set(requirement.candidatePath, existingMode | requirement.mode);\n  }\n\n  for (const [candidatePath, mode] of requirements) {\n    try {\n      accessSync(candidatePath, mode);\n    } catch (_error) {\n      const label = plan.target === 'kimi' ? 'Kimi' : 'Managed install';\n      throw new Error(\n        `${label} destination is not writable by the current user: ${candidatePath}. `\n        + 'Fix the project ownership or permissions, then retry.'\n      );\n    }\n  }\n}\n\nfunction preflightManagedPlan(plan, dependencies = {}) {\n  if (!plan || !Array.isArray(plan.operations)) {\n    throw new Error('A managed install plan with operations is required.');\n  }\n  if (typeof plan.installStatePath !== 'string' || plan.installStatePath.length === 0) {\n    throw new Error('A managed install-state path is required before preflight.');\n  }\n  const ownership = readOwnedDestinations(plan, dependencies);\n  const operations = plan.operations.map(operation => {\n    assertSafeInstallOperation(plan, operation);\n    return {\n      destinationPath: operation.destinationPath,\n      kind: operation.kind,\n      classification: classifyManagedOperation(operation, ownership.destinations),\n    };\n  });\n  assertManagedDestinationsWritable(plan, dependencies);\n  return {\n    plan,\n    operations,\n    ownershipSnapshot: {","sourceCodeStart":327,"sourceCodeEnd":363,"githubUrl":"https://github.com/affaan-m/ECC/blob/8321021c54d670126ce3b2969d5deb880b4b0c2a/scripts/lib/multi-harness-setup.js#L327-L363","documentation":"preflightManagedPlan validates that the caller passed a real managed install plan containing an operations array before doing any work. If plan is null/undefined or plan.operations is not an array, it throws immediately. This is a guard against callers (preview/result/latestPreview) passing an un-built or corrupt plan object.","triggerScenarios":"Calling preview(), result(), or latestPreview() with no plan, a plan object that never went through createMultiHarnessPlan, or a plan whose operations field was reassigned or serialized away (e.g. lost as JSON without operations).","commonSituations":"Passing the output of a failed/aborted plan build; destructuring or transforming a plan and dropping the operations field; calling preview with null on an early-return code path.","solutions":["Create the plan via createMultiHarnessPlan() before calling preview/result","Inspect the plan object: it must have a non-empty operations array","If a plan was persisted/serialized, persist and restore operations too"],"exampleFix":"// before\nawait preview(null);\n// after\nconst plan = await createMultiHarnessPlan(request);\nawait preview(plan);","handlingStrategy":"type-guard","validationCode":"if (!plan || !Array.isArray(plan.operations) || plan.operations.length === 0) {\n  throw new Error('caller bug: plan has no operations');\n}","typeGuard":"function isManagedPlan(p) {\n  return Boolean(p) && Array.isArray(p.operations) && typeof p.installStatePath === 'string' && p.installStatePath.length > 0;\n}","tryCatchPattern":"try {\n  await preview(plan);\n} catch (e) {\n  if (e.message.includes('managed install plan with operations')) {\n    plan = await createMultiHarnessPlan(request); // rebuild and retry once\n  } else throw e;\n}","preventionTips":["Always obtain plans from createMultiHarnessPlan, never hand-build them","Don't partially destructure/reassign plan objects","Validate plans with a guard after deserialization"],"tags":["validation","install-plan"],"backgroundTag":"missing-required-argument","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"}