prisma/prisma · error

PSL_ORPHANED_BASE

PSL_ORPHANED_BASE

Error message

Model "${variantName}" declares @@base(${baseDecl.baseName}, ...) but "${baseDecl.baseName}" has no @@discriminator

What it means

A variant points its `@@base(baseName, value)` at a model that exists but has no `@@discriminator`. `resolvePolymorphism` checks that the base is registered as a discriminator base (interpreter.ts:1742); a variant without a discriminator base is meaningless, so it is rejected. Note this is distinct from PSL_BASE_TARGET_NOT_FOUND, which fires when the base name does not exist at all.

Source

Thrown at packages/2-sql/2-authoring/contract-psl/src/interpreter.ts:1744

      ...patched,
      [coordinateFor(modelName)]: { ...model, discriminator: { field: decl.fieldName }, variants },
    };
  }

  for (const [variantName, baseDecl] of baseDeclarations) {
    if (!modelNames.has(baseDecl.baseName)) {
      diagnostics.push({
        code: 'PSL_BASE_TARGET_NOT_FOUND',
        message: `Model "${variantName}" @@base references non-existent model "${baseDecl.baseName}"`,
        sourceId,
        span: baseDecl.span,
      });
      continue;
    }

    if (!discriminatorDeclarations.has(baseDecl.baseName)) {
      diagnostics.push({
        code: 'PSL_ORPHANED_BASE',
        message: `Model "${variantName}" declares @@base(${baseDecl.baseName}, ...) but "${baseDecl.baseName}" has no @@discriminator`,
        sourceId,
        span: baseDecl.span,
      });
      continue;
    }

    if (discriminatorDeclarations.has(variantName)) {
      continue;
    }

    const variantModel = patched[coordinateFor(variantName)];
    if (!variantModel) continue;

    const baseMapping = modelMappings.get(baseDecl.baseName);
    const variantMapping = modelMappings.get(variantName);
    const hasExplicitMap =
      variantMapping?.model.attributes.some((attr) => attr.name === 'map') ?? false;

View on GitHub (pinned to 1243cdffbe)

Solutions

  1. Add `@@discriminator(field)` to the referenced base model (with a String field).
  2. If the base should not be polymorphic, remove the `@@base(...)` attribute from the variant.
  3. Double-check you are pointing `@@base(...)` at the model that owns the discriminator, not another variant.

Example fix

// before
model Animal { id Int @id }
model Dog { @@base(Animal, "dog") }
// after
model Animal { id Int @id; kind String; @@discriminator(kind) }
model Dog { @@base(Animal, "dog") }
Defensive patterns

Strategy: validation

Validate before calling

// Pre-flight: every @@base(baseName, ...) must point at a model that itself
// declares @@discriminator.
import type { ParsedModel } from './schema-types';

export function findOrphanedBases(
  models: readonly ParsedModel[],
): { variant: string; baseName: string }[] {
  const discriminating = new Set(
    models
      .filter((m) => (m.attributes ?? []).some((a) => a.name === 'discriminator'))
      .map((m) => m.name),
  );
  const problems: { variant: string; baseName: string }[] = [];
  for (const model of models) {
    for (const attr of model.attributes ?? []) {
      if (attr.name !== 'base') continue;
      const baseName = attr.args['base'] as string;
      if (!discriminating.has(baseName)) problems.push({ variant: model.name, baseName });
    }
  }
  return problems;
}

Type guard

import type { Result } from '@prisma-next/utils/result';
import type { Contract, ContractSourceDiagnostics, ContractSourceDiagnostic } from '@prisma-next/config/config-types';

export function isOrphanedBaseError(
  result: Result<Contract, ContractSourceDiagnostics>,
): result is { ok: false; failure: ContractSourceDiagnostics } {
  return !result.ok && result.failure.diagnostics.some(
    (d: ContractSourceDiagnostic) => d.code === 'PSL_ORPHANED_BASE',
  );
}

Prevention

When it happens

Trigger: Declaring `@@base(Animal, "dog")` where `model Animal` exists but lacks `@@discriminator`; forgetting to add the discriminator attribute to the intended base model.

Common situations: Setting up inheritance and forgetting the base-side attribute; removing a discriminator while leaving variants in place; confusing the base/variant attribute direction.

Related errors


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