{"record":{"id":"b679076af3d6bb5c","repo":"OrchardCMS/OrchardCore","slug":"content-part-name-contains-invalid-characters","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/ContentPartDefinitionBuilder.cs","lineNumber":48,"sourceCode":"        else\n        {\n            Name = existing.Name;\n            _fields = existing.Fields.ToList();\n            _settings = existing.Settings.Clone();\n        }\n    }\n\n    public string Name { get; private set; }\n\n    public ContentPartDefinition Build()\n    {\n        if (!char.IsLetter(Name[0]))\n        {\n            throw new ArgumentException(\"Content part name must start with a letter\", \"name\");\n        }\n        if (!string.Equals(Name, Name.ToSafeName(), StringComparison.OrdinalIgnoreCase))\n        {\n            throw new ArgumentException(\"Content part name contains invalid characters\", \"name\");\n        }\n        if (Name.IsReservedContentName())\n        {\n            throw new ArgumentException(\"Content part name is reserved for internal use\", \"name\");\n        }\n\n        return new ContentPartDefinition(Name, _fields, _settings);\n    }\n\n    public ContentPartDefinitionBuilder Named(string name)\n    {\n        Name = name;\n\n        return this;\n    }\n\n    public ContentPartDefinitionBuilder RemoveField(string fieldName)\n    {","sourceCodeStart":30,"sourceCodeEnd":66,"githubUrl":"https://github.com/OrchardCMS/OrchardCore/blob/4306c0717fe573f6fca1b4955909ddab6a192807/src/OrchardCore/OrchardCore.ContentManagement.Abstractions/Metadata/Builders/ContentPartDefinitionBuilder.cs#L30-L66","documentation":"ContentPartDefinitionBuilder.Build throws ArgumentException when the part name differs from its ToSafeName() form (case-insensitive), meaning it contains characters not allowed in safe names (spaces, dashes, symbols, non-ASCII, etc.).","triggerScenarios":"builder.Named(\"My Part\") or Named(\"My-Part\") or any name with punctuation/whitespace, then Build(); names derived from user input or external systems without sanitization.","commonSituations":"Importing part names from CSV/external CMS with spaces, camelCase names with dots or underscores beyond safe rules, copy-pasted display names used as technical names.","solutions":["Convert the name with ToSafeName() before calling Named(): builder.Named(raw.ToSafeName()).","Strip invalid characters manually (letters/digits only) and ensure the first char is a letter.","Validate the name in UI/migration code before persisting definitions."],"exampleFix":"// before\nbuilder.Named(\"My Part\").Build(); // throws\n\n// after\nbuilder.Named(\"My Part\".ToSafeName()).Build(); // \"MyPart\"","handlingStrategy":"validation","validationCode":"string safe = rawName.ToSafeName();\nbool ok = string.Equals(rawName, safe, StringComparison.OrdinalIgnoreCase);","typeGuard":null,"tryCatchPattern":"try\n{\n    builder.Named(rawName);\n    var def = builder.Build();\n}\ncatch (ArgumentException e)\n{\n    _logger.LogError(e, \"Part name '{Name}' is not a safe name\", rawName);\n}","preventionTips":["Always run ToSafeName() on externally sourced names before Named().","Distinguish display names (any text) from technical names (safe names).","Sanitize in import/admin UI before calling AlterPartDefinitionAsync."],"tags":["naming","content-part","validation"],"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"}