prisma/prisma · error

PLANNING_FAILED

PLANNING_FAILED

Error message

Migration planning failed due to conflicts

What it means

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.

Source

Thrown at packages/1-framework/3-tooling/cli/src/control-api/operations/db-run.ts:335

      : `Orphan contract-space markers detected for ${orphans.length} spaces`;
  return new CliStructuredError('MIGRATION.CONTRACT_SPACE_VIOLATION', summary, {
    why: `The database has \`_prisma_marker\` rows for spaces (${orphans
      .map((s) => `"${s}"`)
      .join(
        ', ',
      )}) that are not declared in the project's \`extensions\`. The aggregate pipeline refuses to advance markers it cannot account for.`,
    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.',
    docsUrl: 'https://pris.ly/contract-spaces',
    meta: {
      violations: orphans.map((spaceId) => ({ kind: 'orphanMarker', spaceId })),
    },
  });
}

function mapPlannerError(error: PlannerError): DbInitResult | DbUpdateResult {
  if (error.kind === 'planFromDiffFailed') {
    const failure: DbInitFailure | DbUpdateFailure = {
      code: 'PLANNING_FAILED',
      summary: 'Migration planning failed due to conflicts',
      conflicts: error.conflicts,
      why: undefined,
      meta: undefined,
    };
    return blindCast<
      DbInitResult | DbUpdateResult,
      'notOk(failure) is shape-compatible with both DbInitResult and DbUpdateResult; the union is the return type of the surrounding function'
    >(notOk(failure));
  }
  if (error.kind === 'extensionPathUnreachable') {
    return buildRunnerFailure({
      summary: `Cannot resolve apply path for extension space "${error.spaceId}"`,
      why: `No path in the on-disk migration graph for extension space "${error.spaceId}" reaches the on-disk head ref hash "${error.target}".`,
      meta: { spaceId: error.spaceId, target: error.target },
    });
  }
  if (error.kind === 'extensionPathUnsatisfiable') {

View on GitHub (pinned to 1243cdffbe)

Solutions

  1. Inspect `result.failure.conflicts[]` — each entry names the specific table/column/invariant and the conflict kind.
  2. Resolve each conflict, typically by authoring an explicit migration step or widening the schema change.
  3. Re-run in `mode: 'plan'` to preview the resolved diff before applying.
  4. If a marker is genuinely stale, reset it per the marker/contract-spaces docs only after confirming the DB actually matches the intended baseline.
  5. For type-narrowing conflicts, introduce an additive widening migration first, then narrow in a follow-up.

Example fix

// before — schema narrows Int -> String with no path
model User { id String @id }  // was Int
// after — author an explicit widening migration edge first
// migration create -> produces a recorded edge the planner can replay,
// then narrow the column in the schema
Defensive patterns

Strategy: validation

Validate before calling

// Run a plan-only pass first to surface planner conflicts before touching the database.
const plan = await client.dbUpdate({ ...opts, mode: 'plan' }); // or dbInit(..., { mode: 'plan' })
if (!plan.ok && plan.failure.code === 'PLANNING_FAILED') {
  for (const c of plan.failure.conflicts ?? []) {
    console.error(`${c.kind}: ${c.summary}${c.why ? ` — ${c.why}` : ''}`);
  }
  // resolve schema conflicts in the contract, then re-plan before any apply.
}

Type guard

import type { DbUpdateResult, DbUpdateFailure } from '@prisma-next/cli/control-api';
const isPlanningFailed = (f: DbUpdateFailure): f is DbUpdateFailure & { code: 'PLANNING_FAILED'; conflicts: readonly MigrationPlannerConflict[] } =>
  f.code === 'PLANNING_FAILED';

const result: DbUpdateResult = await client.dbUpdate(opts);
if (!result.ok && isPlanningFailed(result.failure)) {
  const conflicts = result.failure.conflicts; // type-narrowed, non-undefined
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of prisma/prisma@1243cdffbe (2026-08-01). Data as JSON: /data/errors/3fd5b09a4be17b6a.json. Report an issue: GitHub.