OrchardCMS/OrchardCore · error · InvalidOperationException

Unable to remove system-defined part.

Error message

Unable to remove system-defined part.

What it means

RemovePartFromTypeAsync detaches a part from a content type, but first checks the part definition's ContentSettings and throws InvalidOperationException if the part IsSystemDefined. System parts are protected from being detached from types.

Solutions

  1. Inspect partDefinition.GetSettings<ContentSettings>().IsSystemDefined and skip system parts when removing parts from a type.
  2. Remove only the parts you added yourself; leave module-declared parts attached.
  3. If the whole type is unwanted, prefer disabling the owning feature rather than mutating its parts.

Example fix

// before
foreach (var part in typeDefinition.Parts)
    await contentDefinitionService.RemovePartFromTypeAsync(part.PartDefinition.Name, typeName);
// after
foreach (var part in typeDefinition.Parts)
    if (!part.PartDefinition.GetSettings<ContentSettings>().IsSystemDefined)
        await contentDefinitionService.RemovePartFromTypeAsync(part.PartDefinition.Name, typeName);
Defensive patterns

Strategy: validation

Validate before calling

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

Type guard

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

Try / catch

try
{
    await contentDefinitionService.RemovePartFromTypeAsync(partName, typeName);
}
catch (InvalidOperationException)
{
    // part is system-defined; leave attached
}

Prevention

When it happens

Trigger: Calling RemovePartFromTypeAsync(partName, typeName) — directly or via RemoveTypeAsync — where the part's ContentSettings.IsSystemDefined is true (e.g. TitlePart, AutoroutePart system parts).

Common situations: Removing all parts from a type in bulk; a RemoveTypeAsync call that first detaches system parts; migrations that reshape built-in types.

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/765441dd3e5b8721. Report an issue: GitHub.

Appendix: source

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

        var typeDefinition = await _contentDefinitionManager.LoadTypeDefinitionAsync(typeName);

        if (typeDefinition == null)
        {
            return;
        }

        var partDefinition = typeDefinition.Parts.FirstOrDefault(p => string.Equals(p.Name, partName, StringComparison.OrdinalIgnoreCase));

        if (partDefinition == null)
        {
            return;
        }

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

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

        await _contentDefinitionManager.AlterTypeDefinitionAsync(typeName, typeBuilder => typeBuilder.RemovePart(partName));

        var context = new ContentPartDetachedContext
        {
            ContentTypeName = typeName,
            ContentPartName = partName,
        };

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

    public async Task<ContentPartDefinition> AddPartAsync(string name)
    {
        if (await _contentDefinitionManager.LoadPartDefinitionAsync(name) is not null)
        {
            throw new Exception(S["Cannot add part named '{0}'. It already exists.", name]);

View on GitHub (pinned to 4306c0717f)