OrchardCMS/OrchardCore · error · InvalidOperationException

Unable to remove system-defined field.

Error message

Unable to remove system-defined field.

What it means

RemoveFieldFromPartAsync detaches a field from a part, but first checks the part definition's ContentSettings and throws InvalidOperationException if the part IsSystemDefined. Fields belonging to system-defined parts are protected from removal.

Solutions

  1. Check partDefinition.GetSettings<ContentSettings>().IsSystemDefined before removing fields and skip system parts.
  2. Only remove fields your own module added to the part definition.
  3. For system parts, leave their fields intact; adjust behavior through the part's settings instead.

Example fix

// before
foreach (var field in partDefinition.Fields)
    await contentDefinitionService.RemoveFieldFromPartAsync(field.Name, partName);
// after
if (!partDefinition.GetSettings<ContentSettings>().IsSystemDefined)
    foreach (var field in partDefinition.Fields)
        await contentDefinitionService.RemoveFieldFromPartAsync(field.Name, partName);
Defensive patterns

Strategy: validation

Validate before calling

// C#
var partDef = await contentDefinitionManager.LoadPartDefinitionAsync(partName);
bool fieldsRemovable = partDef is null || !partDef.GetSettings<ContentSettings>().IsSystemDefined;

Type guard

static bool CanRemoveFields(ContentPartDefinition partDef) =>
    partDef is not null && !partDef.GetSettings<ContentSettings>().IsSystemDefined;

Try / catch

try
{
    await contentDefinitionService.RemoveFieldFromPartAsync(fieldName, partName);
}
catch (InvalidOperationException)
{
    // system-defined part: fields are protected
}

Prevention

When it happens

Trigger: Calling RemoveFieldFromPartAsync(fieldName, partName) — directly or via RemovePartAsync, which removes all fields of the part first — where the part's ContentSettings.IsSystemDefined is true.

Common situations: Wiping all fields from a part in a migration; trying to strip fields from a built-in part like TitlePart; generic cleanup loops over part.Fields.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


AI-assisted analysis of OrchardCMS/OrchardCore@4306c0717f (2026-09-13). Data as JSON: /api/errors/0336ec751b66be3b. Report an issue: GitHub.

Appendix: source

Thrown at src/OrchardCore.Modules/OrchardCore.ContentTypes/Services/ContentDefinitionService.cs:319

            ContentFieldName = fieldName,
            ContentFieldDisplayName = displayName,
        }, _logger);
    }

    public async Task RemoveFieldFromPartAsync(string fieldName, string partName)
    {
        var partDefinition = await _contentDefinitionManager.LoadPartDefinitionAsync(partName);

        if (partDefinition == null)
        {
            return;
        }

        var settings = partDefinition.GetSettings<ContentSettings>();

        if (settings.IsSystemDefined)
        {
            throw new InvalidOperationException("Unable to remove system-defined field.");
        }

        await _contentDefinitionManager.AlterPartDefinitionAsync(partName, typeBuilder => typeBuilder.RemoveField(fieldName));

        var context = new ContentFieldDetachedContext
        {
            ContentPartName = partName,
            ContentFieldName = fieldName,
        };

        _contentDefinitionEventHandlers.Invoke((handler, ctx) => handler.ContentFieldDetached(ctx), context, _logger);
    }

    public async Task AlterFieldAsync(AlterFieldContext context)
    {
        await _contentDefinitionManager.AlterPartDefinitionAsync(context.PartName, partBuilder =>
        {
            partBuilder.WithField(context.FieldName, fieldBuilder =>

View on GitHub (pinned to 4306c0717f)