OrchardCMS/OrchardCore · error · ArgumentException

Content type name contains invalid characters

Error message

Content type name contains invalid characters

What it means

ContentDefinitionService.AddTypeAsync validates the proposed content type name: it must start with an ASCII letter and must equal its ToSafeName() form (case-insensitive). If the name contains characters that would be altered or stripped by the safe-name normalization (spaces, digits leading, symbols, non-ASCII), an ArgumentException is thrown rather than silently mutating the caller's name.

Solutions

  1. Sanitize the name with the .ToSafeName() string extension before calling AddTypeAsync.
  2. Ensure the name starts with an ASCII letter and contains only letters, digits, and hyphens (no spaces or symbols).
  3. If the user-facing label differs from the technical name, pass a safe technical name and keep the label in the type's display name settings.

Example fix

// before
await contentDefinitionService.AddTypeAsync("Product Category", template => { });
// after
await contentDefinitionService.AddTypeAsync("Product Category".ToSafeName(), template => { }); // "ProductCategory"
Defensive patterns

Strategy: validation

Validate before calling

// C#
static bool IsValidContentTypeName(string name) =>
    !string.IsNullOrEmpty(name)
    && char.IsAsciiLetter(name[0])
    && string.Equals(name, name.ToSafeName(), StringComparison.OrdinalIgnoreCase);
// call AddTypeAsync only if IsValidContentTypeName(name)

Type guard

static bool IsSafeName(string name) =>
    !string.IsNullOrWhiteSpace(name) && name == name.ToSafeName();

Try / catch

try
{
    await contentDefinitionService.AddTypeAsync(name, configure);
}
catch (ArgumentException ex)
{
    logger.LogWarning(ex, "Invalid content type name: {Name}", name);
}

Prevention

When it happens

Trigger: Calling IContentDefinitionService.AddTypeAsync(name, ...) with a name that does not survive ToSafeName(), e.g. "My Type!", "1Widget", "Type-Ünï", or containing '/' or '.'.

Common situations: Deriving a type name from user input, a file name, or a display label; generating type names programmatically from localized strings; building type names by concatenation with separators.

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.

Related errors


AI-assisted analysis of OrchardCMS/OrchardCore@4306c0717f (2026-09-13). Data as JSON: /api/errors/23ccfe234f5ca12c. Report an issue: GitHub.

Appendix: source

Thrown at src/OrchardCore.Modules/OrchardCore.ContentTypes/Services/ContentDefinitionService.cs:68

    {
        if (string.IsNullOrWhiteSpace(displayName))
        {
            throw new ArgumentException($"The '{nameof(displayName)}' can't be null or empty.", nameof(displayName));
        }

        if (string.IsNullOrWhiteSpace(name))
        {
            name = await GenerateContentTypeNameFromDisplayNameAsync(displayName);
        }
        else
        {
            if (!char.IsAsciiLetter(name[0]))
            {
                throw new ArgumentException("Content type name must start with a letter", nameof(name));
            }
            if (!string.Equals(name, name.ToSafeName(), StringComparison.OrdinalIgnoreCase))
            {
                throw new ArgumentException("Content type name contains invalid characters", nameof(name));
            }
        }

        while (await _contentDefinitionManager.LoadTypeDefinitionAsync(name) is not null)
        {
            name = VersionName(name);
        }

        var contentTypeDefinition = new ContentTypeDefinition(name, displayName);

        await _contentDefinitionManager.StoreTypeDefinitionAsync(contentTypeDefinition);

        // Ensure it has its own part.
        await _contentDefinitionManager.AlterTypeDefinitionAsync(name, builder => builder.WithPart(name));
        await _contentDefinitionManager.AlterTypeDefinitionAsync(name, cfg =>
        {
            cfg.Creatable()
                .Draftable()

View on GitHub (pinned to 4306c0717f)