{"record":{"id":"9ae3982a19ceed79","repo":"OrchardCMS/OrchardCore","slug":"the-type-must-inherit-from-contentpart","errorCode":null,"errorMessage":"The type must inherit from ContentPart","messagePattern":"The type must inherit from ContentPart","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/OrchardCore/OrchardCore.ContentManagement.Abstractions/ContentOptions.cs","lineNumber":40,"sourceCode":"    public IReadOnlyList<ContentFieldOption> ContentFieldOptions => _contentFields;\n\n    internal void AddPartHandler(Type contentPartType, Type handlerType)\n    {\n        var option = GetOrAddContentPart(contentPartType);\n        option.AddHandler(handlerType);\n    }\n\n    internal void RemovePartHandler(Type contentPartType, Type handlerType)\n    {\n        var option = GetOrAddContentPart(contentPartType);\n        option.RemoveHandler(handlerType);\n    }\n\n    internal ContentPartOption GetOrAddContentPart(Type contentPartType)\n    {\n        if (!contentPartType.IsSubclassOf(typeof(ContentPart)))\n        {\n            throw new ArgumentException(\"The type must inherit from \" + nameof(ContentPart));\n        }\n\n        var option = _contentParts.FirstOrDefault(x => x.Type == contentPartType);\n        if (option == null)\n        {\n            option = new ContentPartOption(contentPartType);\n            _contentParts.Add(option);\n        }\n\n        return option;\n    }\n\n    internal void AddFieldHandler(Type contentFieldType, Type handlerType)\n    {\n        var option = GetOrAddContentField(contentFieldType);\n        option.AddHandler(handlerType);\n    }\n","sourceCodeStart":22,"sourceCodeEnd":58,"githubUrl":"https://github.com/OrchardCMS/OrchardCore/blob/4306c0717fe573f6fca1b4955909ddab6a192807/src/OrchardCore/OrchardCore.ContentManagement.Abstractions/ContentOptions.cs#L22-L58","documentation":"ContentOptions.GetOrAddContentPart throws ArgumentException when the given Type does not derive from ContentPart. Only ContentPart subclasses can have content part options registered in the content metadata options.","triggerScenarios":"Calling AddContentPart<T> (or ContentOptions.GetOrAddContentPart directly) with a type that is not a ContentPart subclass, e.g. a ContentField, ContentPartOption wrapper, interface, or plain POCO.","commonSituations":"Copy-paste registering a field type with AddContentPart, wrong generic parameter in Startup.cs, registering a view model or record instead of the part class.","solutions":["Make sure the type passed to AddContentPart<T> inherits from ContentPart.","If you meant to register a field, call AddContentField<T> instead.","Check for accidental use of a ContentPartOption/other wrapper type as the generic argument."],"exampleFix":"// before\nservices.AddContentPart<MyField>(); // MyField : ContentField\n\n// after\nservices.AddContentField<MyField>();","handlingStrategy":"validation","validationCode":"if (!typeof(ContentPart).IsAssignableFrom(typeof(T)))\n    throw new ArgumentException(\"T must inherit from ContentPart\");","typeGuard":"bool IsContentPart(Type t) => typeof(ContentPart).IsAssignableFrom(t) && !t.IsAbstract; // adjust as needed","tryCatchPattern":"try\n{\n    services.AddContentPart<T>();\n}\ncatch (ArgumentException e)\n{\n    throw new InvalidOperationException(\"AddContentPart requires a ContentPart subclass\", e);\n}","preventionTips":["Check the class hierarchy before registering: parts extend ContentPart, fields extend ContentField.","Use AddContentField<T> for fields, AddContentPart<T> for parts.","Centralize part/field registration in one Startup location for review."],"tags":["content-part","invalid-argument","registration"],"backgroundTag":"invalid-argument-value","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"}