{"id":"3fd5b09a4be17b6a","repo":"prisma/prisma","slug":"planning-failed","errorCode":"PLANNING_FAILED","errorMessage":"Migration planning failed due to conflicts","messagePattern":"Migration planning failed due to conflicts","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/1-framework/3-tooling/cli/src/control-api/operations/db-run.ts","lineNumber":335,"sourceCode":"      : `Orphan contract-space markers detected for ${orphans.length} spaces`;\n  return new CliStructuredError('MIGRATION.CONTRACT_SPACE_VIOLATION', summary, {\n    why: `The database has \\`_prisma_marker\\` rows for spaces (${orphans\n      .map((s) => `\"${s}\"`)\n      .join(\n        ', ',\n      )}) that are not declared in the project's \\`extensions\\`. The aggregate pipeline refuses to advance markers it cannot account for.`,\n    fix: 'Either re-declare the missing extension(s) in `extensions` (so the aggregate owns them again), or remove the orphan marker row(s) from `_prisma_marker` once you have confirmed the corresponding tables can be safely retired.',\n    docsUrl: 'https://pris.ly/contract-spaces',\n    meta: {\n      violations: orphans.map((spaceId) => ({ kind: 'orphanMarker', spaceId })),\n    },\n  });\n}\n\nfunction mapPlannerError(error: PlannerError): DbInitResult | DbUpdateResult {\n  if (error.kind === 'planFromDiffFailed') {\n    const failure: DbInitFailure | DbUpdateFailure = {\n      code: 'PLANNING_FAILED',\n      summary: 'Migration planning failed due to conflicts',\n      conflicts: error.conflicts,\n      why: undefined,\n      meta: undefined,\n    };\n    return blindCast<\n      DbInitResult | DbUpdateResult,\n      'notOk(failure) is shape-compatible with both DbInitResult and DbUpdateResult; the union is the return type of the surrounding function'\n    >(notOk(failure));\n  }\n  if (error.kind === 'extensionPathUnreachable') {\n    return buildRunnerFailure({\n      summary: `Cannot resolve apply path for extension space \"${error.spaceId}\"`,\n      why: `No path in the on-disk migration graph for extension space \"${error.spaceId}\" reaches the on-disk head ref hash \"${error.target}\".`,\n      meta: { spaceId: error.spaceId, target: error.target },\n    });\n  }\n  if (error.kind === 'extensionPathUnsatisfiable') {","sourceCodeStart":317,"sourceCodeEnd":353,"githubUrl":"https://github.com/prisma/prisma/blob/1243cdffbec0506c595ac8fd5865fe258c336fa0/packages/1-framework/3-tooling/cli/src/control-api/operations/db-run.ts#L317-L353","documentation":"Returned by `db init` / `db update` when mapPlannerError receives a PlannerError of kind `planFromDiffFailed` (db-run.ts:333-345). The migration planner could not produce a plan from the diff between the live database marker state and the target contract; the `conflicts` array enumerates the specific blockers. This is a hard planning failure — no operations are produced, so nothing is applied.","triggerScenarios":"Running `db init` or `db update` (plan or apply) where planMigration's diff yields conflicts — e.g., renaming a column the planner can't widen in place, narrowing a column type with no widening path, dropping a required invariant, or a marker hash the planner can't reason about.","commonSituations":"Editing a schema in a way the planner deems non-migratable in place; a stale `_prisma_marker` row pointing at a hash absent from the on-disk graph; switching a column type without an intermediate widening migration; conflicting changes merged from two branches.","solutions":["Inspect `result.failure.conflicts[]` — each entry names the specific table/column/invariant and the conflict kind.","Resolve each conflict, typically by authoring an explicit migration step or widening the schema change.","Re-run in `mode: 'plan'` to preview the resolved diff before applying.","If a marker is genuinely stale, reset it per the marker/contract-spaces docs only after confirming the DB actually matches the intended baseline.","For type-narrowing conflicts, introduce an additive widening migration first, then narrow in a follow-up."],"exampleFix":"// before — schema narrows Int -> String with no path\nmodel User { id String @id }  // was Int\n// after — author an explicit widening migration edge first\n// migration create -> produces a recorded edge the planner can replay,\n// then narrow the column in the schema","handlingStrategy":"validation","validationCode":"// Run a plan-only pass first to surface planner conflicts before touching the database.\nconst plan = await client.dbUpdate({ ...opts, mode: 'plan' }); // or dbInit(..., { mode: 'plan' })\nif (!plan.ok && plan.failure.code === 'PLANNING_FAILED') {\n  for (const c of plan.failure.conflicts ?? []) {\n    console.error(`${c.kind}: ${c.summary}${c.why ? ` — ${c.why}` : ''}`);\n  }\n  // resolve schema conflicts in the contract, then re-plan before any apply.\n}","typeGuard":"import type { DbUpdateResult, DbUpdateFailure } from '@prisma-next/cli/control-api';\nconst isPlanningFailed = (f: DbUpdateFailure): f is DbUpdateFailure & { code: 'PLANNING_FAILED'; conflicts: readonly MigrationPlannerConflict[] } =>\n  f.code === 'PLANNING_FAILED';\n\nconst result: DbUpdateResult = await client.dbUpdate(opts);\nif (!result.ok && isPlanningFailed(result.failure)) {\n  const conflicts = result.failure.conflicts; // type-narrowed, non-undefined\n}","tryCatchPattern":null,"preventionTips":["Always run mode: 'plan' (or the CLI --plan / dry-run) in CI and review warnings/conflicts before any apply reaches a database.","Keep migrations linear and append-only; PLANNING_FAILED usually follows a non-additive schema change the planner cannot reconcile (type/nullability conflicts).","When a conflict appears, fix it at the contract/schema source rather than hand-editing migration files."],"tags":["migration","planning","db","conflicts","schema-diff"],"analyzedSha":"1243cdffbec0506c595ac8fd5865fe258c336fa0","analyzedAt":"2026-08-01T19:42:02.087Z","schemaVersion":2}