OrchardCMS/OrchardCore · error · ArgumentException

Content part name contains invalid characters

Error message

Content part name contains invalid characters

What it means

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.).

Solutions

  1. Convert the name with ToSafeName() before calling Named(): builder.Named(raw.ToSafeName()).
  2. Strip invalid characters manually (letters/digits only) and ensure the first char is a letter.
  3. Validate the name in UI/migration code before persisting definitions.

Example fix

// before
builder.Named("My Part").Build(); // throws

// after
builder.Named("My Part".ToSafeName()).Build(); // "MyPart"
Defensive patterns

Strategy: validation

Validate before calling

string safe = rawName.ToSafeName();
bool ok = string.Equals(rawName, safe, StringComparison.OrdinalIgnoreCase);

Try / catch

try
{
    builder.Named(rawName);
    var def = builder.Build();
}
catch (ArgumentException e)
{
    _logger.LogError(e, "Part name '{Name}' is not a safe name", rawName);
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

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/b679076af3d6bb5c. Report an issue: GitHub.

Appendix: source

Thrown at src/OrchardCore/OrchardCore.ContentManagement.Abstractions/Metadata/Builders/ContentPartDefinitionBuilder.cs:48

        else
        {
            Name = existing.Name;
            _fields = existing.Fields.ToList();
            _settings = existing.Settings.Clone();
        }
    }

    public string Name { get; private set; }

    public ContentPartDefinition Build()
    {
        if (!char.IsLetter(Name[0]))
        {
            throw new ArgumentException("Content part name must start with a letter", "name");
        }
        if (!string.Equals(Name, Name.ToSafeName(), StringComparison.OrdinalIgnoreCase))
        {
            throw new ArgumentException("Content part name contains invalid characters", "name");
        }
        if (Name.IsReservedContentName())
        {
            throw new ArgumentException("Content part name is reserved for internal use", "name");
        }

        return new ContentPartDefinition(Name, _fields, _settings);
    }

    public ContentPartDefinitionBuilder Named(string name)
    {
        Name = name;

        return this;
    }

    public ContentPartDefinitionBuilder RemoveField(string fieldName)
    {

View on GitHub (pinned to 4306c0717f)