dotnet/efcore · error · InvalidOperationException

Named default constraints cannot be used with TPC or entity…

Error message

Named default constraints cannot be used with TPC or entity splitting if they result in non-unique constraint names. Constraint name: '{constraintNameCandidate}'.

What it means

SharedTableConvention.TryUniquifyDefaultConstraint fires when a property with a default value/SQL maps to more than one table (TPC inheritance or entity splitting). Default-constraint names must be unique per database; EF would otherwise generate the SAME implicit name for each table, causing a clash. When no explicit default-constraint-name configuration source is present, EF cannot disambiguate and throws rather than emit invalid DDL (tracked by issue #27970).

Solutions

  1. Remove the default value/SQL from the shared property, or remap so the property lives on a single table (e.g. switch from TPC to TPH).
  2. Provide an explicit, per-table-unique default-constraint name only if your scenario is supported (see [459] — currently still unsupported for TPC/splitting), otherwise prefer removing the default.
  3. Move the default-bearing property to a non-shared entity so it maps to one table.
  4. Track issue #27970 for per-table explicit default-constraint name support.

Example fix

// before — TPC + default value on a property shared across tables -> [458]
modelBuilder.Entity<Animal>().UseTpcMapping()
    .Property(a => a.Legs).HasDefaultValue(4);

// after — drop the default (or remap to a single table / TPH)
modelBuilder.Entity<Animal>().UseTpcMapping()
    .Property(a => a.Legs);
// (apply the default at insert time in code instead)
Defensive patterns

Strategy: validation

Validate before calling

// Detect properties with defaults that map to multiple tables (TPC/splitting) without an explicit name.
static IEnumerable<IProperty> PropertiesWithClashingImplicitDefaults(IModel model)
    => model.GetEntityTypes()
        .SelectMany(et => et.GetProperties())
        .Where(p => p.GetMappedStoreObjects(StoreObjectType.Table).Count() > 1
                    && p.GetDefaultConstraintNameConfigurationSource() is null
                    && (p.GetDefaultValue() is not null || p.GetDefaultValueSql() is not null));

Prevention

When it happens

Trigger: A property carrying .HasDefaultValue(...) / .HasDefaultValueSql(...) in a TPC-mapped hierarchy or a split entity, where the property maps to multiple tables and the implicit (generated) default-constraint name collides across them, with no explicit name configured.

Common situations: Adopting TPC mapping on a hierarchy whose base properties have defaults; entity splitting combined with default values; introducing .HasDefaultValue after migrating to TPC.

Related errors


AI-assisted analysis of dotnet/efcore@3a2006ef56 (2026-08-11). Data as JSON: /api/errors/8373bde312764809. Report an issue: GitHub.

Appendix: source

Thrown at src/EFCore.Relational/Metadata/Conventions/SharedTableConvention.cs:768

    private static string? TryUniquifyDefaultConstraint(
        IConventionProperty property,
        string constraintName,
        string? schema,
        Dictionary<(string, string?), (IConventionProperty, StoreObjectIdentifier)> defaultConstraints,
        in StoreObjectIdentifier storeObject,
        int maxLength)
    {
        var mappedTables = property.GetMappedStoreObjects(StoreObjectType.Table);
        if (mappedTables.Count() > 1)
        {
            // For TPC and some entity splitting scenarios we end up with multiple tables having to define the constraint.
            // Since constraint name has to be unique, we can't keep the same name for all
            // Disabling this scenario until we have better way to configure the constraint name
            // see issue #27970
            if (property.GetDefaultConstraintNameConfigurationSource() == null)
            {
                throw new InvalidOperationException(
                    RelationalStrings.ImplicitDefaultNamesNotSupportedForTpcWhenNamesClash(constraintName));
            }

            throw new InvalidOperationException(
                RelationalStrings.ExplicitDefaultConstraintNamesNotSupportedForTpc(constraintName));
        }

        if (property.Builder.CanSetAnnotation(RelationalAnnotationNames.DefaultConstraintName, null))
        {
            constraintName = Uniquifier.Uniquify(constraintName, defaultConstraints, n => (n, schema), maxLength);
            property.Builder.HasAnnotation(RelationalAnnotationNames.DefaultConstraintName, constraintName);
            return constraintName;
        }

        return null;
    }

    private void UniquifyTriggerNames(

View on GitHub (pinned to 3a2006ef56)