{"record":{"id":"c6618c8ec5a39123","repo":"OrchardCMS/OrchardCore","slug":"content-part-name-contains-invalid-characters-c6618c","errorCode":null,"errorMessage":"Content part name contains invalid characters","messagePattern":"Content part name contains invalid characters","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/OrchardCore/OrchardCore.ContentManagement.Abstractions/Metadata/Builders/ContentTypeDefinitionBuilder.cs","lineNumber":219,"sourceCode":"        private readonly ContentPartDefinition _partDefinition;\n\n        public PartConfigurerImpl(ContentTypePartDefinition part)\n            : base(part)\n        {\n            Current = part;\n            _partDefinition = part.PartDefinition;\n        }\n\n        public override ContentTypePartDefinition Build()\n        {\n            if (!char.IsLetter(Current.Name[0]))\n            {\n                throw new ArgumentException(\"Content part name must start with a letter\", \"name\");\n            }\n\n            if (!string.Equals(Current.Name, Current.Name.ToSafeName(), StringComparison.OrdinalIgnoreCase))\n            {\n                throw new ArgumentException(\"Content part name contains invalid characters\", \"name\");\n            }\n\n            return new ContentTypePartDefinition(Current.Name, _partDefinition, _settings)\n            {\n                ContentTypeDefinition = Current.ContentTypeDefinition,\n            };\n        }\n    }\n}\n","sourceCodeStart":201,"sourceCodeEnd":229,"githubUrl":"https://github.com/OrchardCMS/OrchardCore/blob/4306c0717fe573f6fca1b4955909ddab6a192807/src/OrchardCore/OrchardCore.ContentManagement.Abstractions/Metadata/Builders/ContentTypeDefinitionBuilder.cs#L201-L229","documentation":"ContentTypeDefinitionBuilder's inner Build() also rejects part names whose value differs from their ToSafeName() result, i.e. names containing spaces, punctuation, or other unsafe characters. Safe names are required for reliable use in placement, drivers, and generated UI.","triggerScenarios":"Calling WithPart with names like 'Order Details', 'Billing/Shipping', or names containing dots or unicode characters during type alteration","commonSituations":"Using display-style names ('Order Details') as technical part names; deriving part names from database column names with spaces; copy-pasted names with invisible whitespace","solutions":["Replace invalid characters: use PascalCase with no spaces ('OrderDetails')","Run the candidate name through ToSafeName() and compare before calling WithPart","Put the human-readable label in the part's display name / settings instead of the technical name"],"exampleFix":"// before\nbuilder.AlterTypeDefinitionAsync(\"Order\", t => t.WithPart(\"Order Details\"));\n// after\nbuilder.AlterTypeDefinitionAsync(\"Order\", t => t.WithPart(\"OrderDetails\"));","handlingStrategy":"validation","validationCode":"if (string.IsNullOrWhiteSpace(partName) || !string.Equals(partName, partName.ToSafeName(), StringComparison.OrdinalIgnoreCase))\n    throw new ArgumentException($\"Part name '{partName}' contains invalid characters.\");","typeGuard":null,"tryCatchPattern":"try\n{\n    await builder.AlterTypeDefinitionAsync(typeName, t => t.WithPart(partName));\n}\ncatch (ArgumentException ex) when (ex.Message.Contains(\"invalid characters\"))\n{\n    _logger.LogError(ex, \"Part name '{Name}' is not a safe name\", partName);\n}","preventionTips":["Use PascalCase technical part names; put spaces only in display labels","Run names through ToSafeName() in code that generates parts dynamically","Watch for invisible whitespace when names come from config or spreadsheets"],"tags":["content-management","validation","naming","content-part"],"backgroundTag":"invalid-identifier-format","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"}