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
- Add `@@discriminator(field)` to the referenced base model (with a String field).
- If the base should not be polymorphic, remove the `@@base(...)` attribute from the variant.
- 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
- Always pair a variant's @@base(Base) with a @@discriminator on Base — they are two halves of one STI/MTI declaration.
- Add @@discriminator to the base first, then the variant's @@base, so the schema is never in a half-wired state.
- If you remove @@discriminator from a base, remove all @@base references to it in the same change.
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
- PSL_DISCRIMINATOR_AND_BASE
- PSL_DUPLICATE_DISCRIMINATOR_VALUE
- PSL_ORPHANED_DISCRIMINATOR
- PSL_INVALID_ATTRIBUTE_ARGUMENT
- PSL_DISCRIMINATOR_AND_BASE
AI-assisted analysis of prisma/prisma@1243cdffbe (2026-08-01).
Data as JSON: /data/errors/543eaf4b2b6b8e8b.json.
Report an issue: GitHub.