OrchardCMS/OrchardCore · error · ArgumentException

Content field name must start with a letter

Error message

Content field name must start with a letter

What it means

Validation performed when a content field is attached to a part via the ContentPartDefinitionBuilder: the field name must start with a letter. It fires during ContentPartDefinition.Build() when a field was added with a name beginning with a digit, symbol, or whitespace, which would produce invalid internal identifiers.

Solutions

  1. Prefix the field name with a letter, e.g. "Year2024" instead of "2024Year" or "F2024".
  2. Validate before building: char.IsLetter(name[0]).
  3. Ensure the field name is non-null and non-empty.

Example fix

// before
partBuilder.WithField("2024sales", f => f.OfType<NumericField>()); // Build throws

// after
partBuilder.WithField("Sales2024", f => f.OfType<NumericField>());
Defensive patterns

Strategy: validation

Validate before calling

bool IsValidFieldName(string name) =>
    !string.IsNullOrEmpty(name) && char.IsLetter(name[0]);

Try / catch

try
{
    var fieldDef = fieldBuilder.Build();
}
catch (ArgumentException e)
{
    _logger.LogError(e, "Invalid content field name '{Name}'", name);
}

Prevention

When it happens

Trigger: BuildField/WithField(...).Build() with a name like "1st" or "-value"; migrations generating field names from data that begin with digits; empty name causing _fieldName[0] to throw.

Common situations: Auto-generated field names from column names like "2024_sales", user-supplied field names not sanitized, empty field name from a recipe typo.

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

Appendix: source

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

    private sealed class FieldConfigurerImpl : ContentPartFieldDefinitionBuilder
    {
        private ContentFieldDefinition _fieldDefinition;
        private readonly ContentPartDefinition _partDefinition;
        private readonly string _fieldName;

        public FieldConfigurerImpl(ContentPartFieldDefinition field, ContentPartDefinition part)
            : base(field)
        {
            _fieldDefinition = field.FieldDefinition;
            _fieldName = field.Name;
            _partDefinition = part;
        }

        public override ContentPartFieldDefinition Build()
        {
            if (!char.IsLetter(_fieldName[0]))
            {
                throw new ArgumentException("Content field name must start with a letter", "name");
            }
            if (!string.Equals(_fieldName, _fieldName.ToSafeName(), StringComparison.OrdinalIgnoreCase))
            {
                throw new ArgumentException("Content field name contains invalid characters", "name");
            }

            return new ContentPartFieldDefinition(_fieldDefinition, _fieldName, _settings);
        }

        public override string Name
            => _fieldName;

        public override string FieldType
            => _fieldDefinition.Name;


        public override string PartName
            => _partDefinition.Name;

View on GitHub (pinned to 4306c0717f)