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
- Inspect partDefinition.GetSettings<ContentSettings>().IsSystemDefined and skip system parts when removing parts from a type.
- Remove only the parts you added yourself; leave module-declared parts attached.
- 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
- Filter out system parts in loops that detach parts from types.
- Remember RemoveTypeAsync internally calls this for each part.
- Prefer feature disablement over stripping module-declared parts.
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
- Unable to remove system-defined type.
- Unable to remove system-defined field.
- The 'displayName' can't be null or empty.
- Content type name must start with a letter
- Content type name contains invalid characters
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)