{"record":{"id":"c7fb3cbfadb508d5","repo":"OrchardCMS/OrchardCore","slug":"content-type-name-contains-invalid-characters","errorCode":null,"errorMessage":"Content type name contains invalid characters","messagePattern":"Content type name contains invalid characters","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/OrchardCore/OrchardCore.ContentManagement.Abstractions/Metadata/Builders/ContentTypeDefinitionBuilder.cs","lineNumber":47,"sourceCode":"        }\n        else\n        {\n            _name = existing.Name;\n            _displayName = existing.DisplayName;\n            _parts = existing.Parts.ToList();\n            _settings = existing.Settings.Clone();\n        }\n    }\n\n    public ContentTypeDefinition Build()\n    {\n        if (!char.IsLetter(_name[0]))\n        {\n            throw new ArgumentException(\"Content type name must start with a letter\", \"name\");\n        }\n        if (!string.Equals(_name, _name.ToSafeName(), StringComparison.OrdinalIgnoreCase))\n        {\n            throw new ArgumentException(\"Content type name contains invalid characters\", \"name\");\n        }\n        if (_name.IsReservedContentName())\n        {\n            throw new ArgumentException(\"Content type name is reserved for internal use\", \"name\");\n        }\n\n        return new ContentTypeDefinition(_name, _displayName, _parts, _settings);\n    }\n\n    [Obsolete(\"This method has been deprecated, please use WithName() instead.\")]\n    public ContentTypeDefinitionBuilder Named(string name) => WithName(name);\n\n    public ContentTypeDefinitionBuilder WithName(string name)\n    {\n        _name = name;\n\n        return this;\n    }","sourceCodeStart":29,"sourceCodeEnd":65,"githubUrl":"https://github.com/OrchardCMS/OrchardCore/blob/4306c0717fe573f6fca1b4955909ddab6a192807/src/OrchardCore/OrchardCore.ContentManagement.Abstractions/Metadata/Builders/ContentTypeDefinitionBuilder.cs#L29-L65","documentation":"ContentTypeDefinitionBuilder.Build() validates the content type name before constructing the ContentTypeDefinition. This error is thrown when the name does not equal its own ToSafeName() result, meaning it contains characters outside the allowed safe set (letters, digits, hyphen, underscore). Orchard requires safe names so they can be used in URLs, identifiers, and database columns.","triggerScenarios":"Calling builder.AlterTypeDefinitionAsync (or WithName) with a type name containing spaces, dots, dashes at invalid positions, punctuation, or non-ASCII characters, e.g. 'Product Category', 'My.Type', 'Blog!'","commonSituations":"Migrations that derive a type name from user input or a display name without sanitizing; copy-pasted names with trailing whitespace; names built by concatenating strings with separators like '.' or '/'","solutions":["Remove or replace invalid characters so the name is only letters, digits, hyphens, or underscores","Use the name.ToSafeName() extension to sanitize before passing it to WithName","Keep the display name (with spaces/unicode) in WithDisplayName and reserve WithName for the safe technical identifier"],"exampleFix":"// before\nbuilder.AlterTypeDefinitionAsync(\"Product Category\", t => t.WithDisplayName(\"Product Category\"));\n// after\nbuilder.AlterTypeDefinitionAsync(\"ProductCategory\", t => t.WithDisplayName(\"Product Category\"));","handlingStrategy":"validation","validationCode":"if (string.IsNullOrWhiteSpace(typeName) || !string.Equals(typeName, typeName.ToSafeName(), StringComparison.OrdinalIgnoreCase))\n    throw new ArgumentException($\"Type name '{typeName}' is not a safe name; use letters, digits, hyphens or underscores.\");","typeGuard":null,"tryCatchPattern":"try\n{\n    await builder.AlterTypeDefinitionAsync(name, configure);\n}\ncatch (ArgumentException ex) when (ex.Message.Contains(\"invalid characters\"))\n{\n    _logger.LogError(ex, \"Content type name '{Name}' is not a safe name\", name);\n}","preventionTips":["Always build technical names with ToSafeName() and keep human labels in display names","Never derive type names from user-entered display text without sanitizing","Add a unit test asserting candidate names equal their ToSafeName result"],"tags":["content-management","validation","naming","migrations"],"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"}