{"record":{"id":"9c111d464a79bc71","repo":"OrchardCMS/OrchardCore","slug":"the-type-must-implement-icontentpartdisplaydriver","errorCode":null,"errorMessage":"The type must implement IContentPartDisplayDriver","messagePattern":"The type must implement IContentPartDisplayDriver","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/OrchardCore/OrchardCore.ContentManagement.Display/ContentDisplay/ContentDisplayOptions.cs","lineNumber":23,"sourceCode":"public class ContentDisplayOptions\n{\n    private readonly List<ContentPartDisplayOption> _contentParts = [];\n    private readonly List<ContentFieldDisplayOption> _contentFields = [];\n\n    private FrozenDictionary<string, ContentPartDisplayOption> _contentPartOptions;\n    private FrozenDictionary<string, ContentFieldDisplayOption> _contentFieldOptions;\n\n    public IReadOnlyDictionary<string, ContentPartDisplayOption> ContentPartOptions\n        => _contentPartOptions ??= _contentParts.ToFrozenDictionary(k => k.Type.Name);\n\n    public IReadOnlyDictionary<string, ContentFieldDisplayOption> ContentFieldOptions\n        => _contentFieldOptions ??= _contentFields.ToFrozenDictionary(k => k.Type.Name);\n\n    internal void ForContentPartDisplayMode(Type contentPartType, Type displayDriverType, Func<string, bool> predicate)\n    {\n        if (!typeof(IContentPartDisplayDriver).IsAssignableFrom(displayDriverType))\n        {\n            throw new ArgumentException(\"The type must implement \" + nameof(IContentPartDisplayDriver));\n        }\n\n        var option = GetOrAddContentPartDisplayOption(contentPartType);\n        option.ForDisplayMode(displayDriverType, predicate);\n    }\n\n    internal void ForContentPartEditor(Type contentPartType, Type editorDriverType, Func<string, bool> predicate)\n    {\n        if (!typeof(IContentPartDisplayDriver).IsAssignableFrom(editorDriverType))\n        {\n            throw new ArgumentException(\"The type must implement \" + nameof(IContentPartDisplayDriver));\n        }\n\n        var option = GetOrAddContentPartDisplayOption(contentPartType);\n        option.ForEditor(editorDriverType, predicate);\n    }\n\n    internal void RemoveContentPartDisplayDriver(Type contentPartType, Type driverType)","sourceCodeStart":5,"sourceCodeEnd":41,"githubUrl":"https://github.com/OrchardCMS/OrchardCore/blob/4306c0717fe573f6fca1b4955909ddab6a192807/src/OrchardCore/OrchardCore.ContentManagement.Display/ContentDisplay/ContentDisplayOptions.cs#L5-L41","documentation":"ContentDisplayOptions.ForContentPartDisplayMode registers a placement/display-mode driver for a content part and validates that the supplied driver type implements IContentPartDisplayDriver. This internal invariant keeps the display pipeline type-safe: only part display drivers can be registered for part display modes.","triggerScenarios":"Calling ForContentPartDisplayMode(partType, driverType, predicate) with a driver type that implements IContentFieldDisplayDriver, IContentDisplayDriver, or nothing at all","commonSituations":"Custom placement/shape table code that passes a field driver where a part driver is required; copy-pasted registration code after refactoring a driver from field to part (or vice versa)","solutions":["Pass a driver class that implements IContentPartDisplayDriver for the part","If the type is a field driver, call the content-field API (ForContentFieldDisplayMode) instead","Fix the driver class itself to implement IContentPartDisplayDriver if it was intended to serve a part"],"exampleFix":"// before\noptions.ForContentPartDisplayMode(typeof(ProductPart), typeof(ProductPartFieldDriver), d => d == \"Detail\");\n// after\noptions.ForContentPartDisplayMode(typeof(ProductPart), typeof(ProductPartDisplayDriver), d => d == \"Detail\");","handlingStrategy":"type-guard","validationCode":"if (!typeof(IContentPartDisplayDriver).IsAssignableFrom(driverType))\n    throw new ArgumentException($\"{driverType.Name} is not an IContentPartDisplayDriver.\");","typeGuard":"static bool IsPartDisplayDriver(Type t) => typeof(IContentPartDisplayDriver).IsAssignableFrom(t);","tryCatchPattern":"try\n{\n    options.ForContentPartDisplayMode(partType, driverType, predicate);\n}\ncatch (ArgumentException ex) when (ex.Message.Contains(nameof(IContentPartDisplayDriver)))\n{\n    _logger.LogError(ex, \"{Type} is not an IContentPartDisplayDriver\", driverType.Name);\n}","preventionTips":["Match the driver base class to the API: part driver for part APIs, field driver for field APIs","Register drivers via typed generics where possible so the compiler catches mismatches","After refactoring a driver's base class, grep for all placement/option registrations of it"],"tags":["display-management","drivers","type-validation","placement"],"backgroundTag":"type-mismatch","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"}