OrchardCMS/OrchardCore · error · ArgumentException
Content type name contains invalid characters
Error message
Content type name contains invalid characters
What it means
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.
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
Example fix
// before
builder.AlterTypeDefinitionAsync("Product Category", t => t.WithDisplayName("Product Category"));
// after
builder.AlterTypeDefinitionAsync("ProductCategory", t => t.WithDisplayName("Product Category")); Defensive patterns
Strategy: validation
Validate before calling
if (string.IsNullOrWhiteSpace(typeName) || !string.Equals(typeName, typeName.ToSafeName(), StringComparison.OrdinalIgnoreCase))
throw new ArgumentException($"Type name '{typeName}' is not a safe name; use letters, digits, hyphens or underscores."); Try / catch
try
{
await builder.AlterTypeDefinitionAsync(name, configure);
}
catch (ArgumentException ex) when (ex.Message.Contains("invalid characters"))
{
_logger.LogError(ex, "Content type name '{Name}' is not a safe name", name);
} Prevention
- 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
When it happens
Trigger: 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!'
Common situations: 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 '/'
Understand the failure class
Background: "invalid id" errors: invalid identifier format — why libraries reject IDs before lookup, and how to fix them — this error's family across 37 libraries.
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Content type name is reserved for internal use
- Content part name must start with a letter
- Content part name contains invalid characters
- Content part name must start with a letter
- Content part name contains invalid characters
AI-assisted analysis of OrchardCMS/OrchardCore@4306c0717f (2026-09-13).
Data as JSON: /api/errors/c7fb3cbfadb508d5.
Report an issue: GitHub.
Appendix: source
Thrown at src/OrchardCore/OrchardCore.ContentManagement.Abstractions/Metadata/Builders/ContentTypeDefinitionBuilder.cs:47
}
else
{
_name = existing.Name;
_displayName = existing.DisplayName;
_parts = existing.Parts.ToList();
_settings = existing.Settings.Clone();
}
}
public ContentTypeDefinition Build()
{
if (!char.IsLetter(_name[0]))
{
throw new ArgumentException("Content type name must start with a letter", "name");
}
if (!string.Equals(_name, _name.ToSafeName(), StringComparison.OrdinalIgnoreCase))
{
throw new ArgumentException("Content type name contains invalid characters", "name");
}
if (_name.IsReservedContentName())
{
throw new ArgumentException("Content type name is reserved for internal use", "name");
}
return new ContentTypeDefinition(_name, _displayName, _parts, _settings);
}
[Obsolete("This method has been deprecated, please use WithName() instead.")]
public ContentTypeDefinitionBuilder Named(string name) => WithName(name);
public ContentTypeDefinitionBuilder WithName(string name)
{
_name = name;
return this;
}View on GitHub (pinned to 4306c0717f)