{"record":{"id":"765441dd3e5b8721","repo":"OrchardCMS/OrchardCore","slug":"unable-to-remove-system-defined-part","errorCode":null,"errorMessage":"Unable to remove system-defined part.","messagePattern":"Unable to remove system-defined part\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/OrchardCore.Modules/OrchardCore.ContentTypes/Services/ContentDefinitionService.cs","lineNumber":201,"sourceCode":"        var typeDefinition = await _contentDefinitionManager.LoadTypeDefinitionAsync(typeName);\n\n        if (typeDefinition == null)\n        {\n            return;\n        }\n\n        var partDefinition = typeDefinition.Parts.FirstOrDefault(p => string.Equals(p.Name, partName, StringComparison.OrdinalIgnoreCase));\n\n        if (partDefinition == null)\n        {\n            return;\n        }\n\n        var settings = partDefinition.GetSettings<ContentSettings>();\n\n        if (settings.IsSystemDefined)\n        {\n            throw new InvalidOperationException(\"Unable to remove system-defined part.\");\n        }\n\n        await _contentDefinitionManager.AlterTypeDefinitionAsync(typeName, typeBuilder => typeBuilder.RemovePart(partName));\n\n        var context = new ContentPartDetachedContext\n        {\n            ContentTypeName = typeName,\n            ContentPartName = partName,\n        };\n\n        _contentDefinitionEventHandlers.Invoke((handler, ctx) => handler.ContentPartDetached(ctx), context, _logger);\n    }\n\n    public async Task<ContentPartDefinition> AddPartAsync(string name)\n    {\n        if (await _contentDefinitionManager.LoadPartDefinitionAsync(name) is not null)\n        {\n            throw new Exception(S[\"Cannot add part named '{0}'. It already exists.\", name]);","sourceCodeStart":183,"sourceCodeEnd":219,"githubUrl":"https://github.com/OrchardCMS/OrchardCore/blob/4306c0717fe573f6fca1b4955909ddab6a192807/src/OrchardCore.Modules/OrchardCore.ContentTypes/Services/ContentDefinitionService.cs#L183-L219","documentation":"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.","triggerScenarios":"Calling RemovePartFromTypeAsync(partName, typeName) — directly or via RemoveTypeAsync — where the part's ContentSettings.IsSystemDefined is true (e.g. TitlePart, AutoroutePart system parts).","commonSituations":"Removing all parts from a type in bulk; a RemoveTypeAsync call that first detaches system parts; migrations that reshape built-in 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."],"exampleFix":"// before\nforeach (var part in typeDefinition.Parts)\n    await contentDefinitionService.RemovePartFromTypeAsync(part.PartDefinition.Name, typeName);\n// after\nforeach (var part in typeDefinition.Parts)\n    if (!part.PartDefinition.GetSettings<ContentSettings>().IsSystemDefined)\n        await contentDefinitionService.RemovePartFromTypeAsync(part.PartDefinition.Name, typeName);","handlingStrategy":"validation","validationCode":"// C#\nvar partDef = await contentDefinitionManager.LoadPartDefinitionAsync(partName);\nbool detachable = partDef is null || !partDef.GetSettings<ContentSettings>().IsSystemDefined;","typeGuard":"static bool CanDetachPart(ContentPartDefinition partDef) =>\n    partDef is not null && !partDef.GetSettings<ContentSettings>().IsSystemDefined;","tryCatchPattern":"try\n{\n    await contentDefinitionService.RemovePartFromTypeAsync(partName, typeName);\n}\ncatch (InvalidOperationException)\n{\n    // part is system-defined; leave attached\n}","preventionTips":["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."],"tags":["contenttypes","system-defined","parts"],"backgroundTag":"unsupported-operation","analyzedSha":"4306c0717fe573f6fca1b4955909ddab6a192807","analyzedAt":"2026-09-13T17:41:05.024Z","contentChangedAt":"2026-09-13T17:41:05.024Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}