Humanizr/Humanizer · error · InvalidOperationException
Enum members require an enum type.
Error message
Enum members require an enum type.
What it means
A contract member with kind 'enum' must specify an EnumType (the C# enum type name) so the factory can emit a fully qualified enum member access. CreateEnumValue checks for null EnumType and throws because it cannot construct 'null.Value' — the enum type name is load-bearing for code generation.
Source
Thrown at src/Humanizer.SourceGenerators/Generators/ProfileCatalogs/NumberToWordsEngineContractFactory.cs:444
static string CreateObjectValue(JsonElement root, EngineContractMember member, bool useCultureParameter)
{
var objectRoot = string.IsNullOrWhiteSpace(member.SourcePath)
? root
: EngineContractUtilities.GetRequiredElement(root, member.SourcePath);
// Nested profile objects let the YAML stay grouped by meaning while the generated code
// still calls an explicit runtime constructor shape. This keeps the authoring surface
// readable without paying any runtime mapping cost.
return member.TypeName is null
? "new(" + CreateConstructorValues(objectRoot, member.Members, useCultureParameter) + ")"
: "new " + member.TypeName + "(" + CreateConstructorValues(objectRoot, member.Members, useCultureParameter) + ")";
}
static string CreateEnumValue(JsonElement root, EngineContractMember member)
{
if (member.EnumType is null)
{
throw new InvalidOperationException("Enum members require an enum type.");
}
return member.EnumType + "." + ToEnumMemberName(GetStringValue(root, member));
}
static string CreateNullableIntStringDictionaryValue(JsonElement root, EngineContractMember member)
{
if (EngineContractUtilities.TryGetElement(root, member.SourcePath, out _))
{
return CreateNullableIntStringFrozenDictionaryExpression(root, EngineContractUtilities.GetLeafPropertyName(member.SourcePath));
}
return member.MissingValue switch
{
"empty" => "FrozenDictionary<int, string>.Empty",
_ => "null"
};
}View on GitHub (pinned to ffc2b77c0f)
Solutions
- Set the enumType parameter on the EngineContractMember to the fully qualified C# enum type name (e.g., 'BillionStrategy').
- If the member should not be an enum, change its kind to 'string' or another appropriate kind.
- Verify the positional argument order in the EngineContractMember constructor matches the parameter list.
Example fix
// before
new EngineContractMember(
kind: "enum",
sourcePath: "billionStrategy",
enumType: null,
...)
// after
new EngineContractMember(
kind: "enum",
sourcePath: "billionStrategy",
enumType: "BillionStrategy",
...) Defensive patterns
Strategy: validation
Validate before calling
// Validate enum members have a type before generation:
foreach (var m in contract.Members)
if (m.Kind == "enum" && string.IsNullOrEmpty(m.EnumType))
throw new ArgumentException("Enum member requires EnumType."); Type guard
static bool IsEnumMemberValid(EngineContractMember m) =>
m.Kind != "enum" || !string.IsNullOrEmpty(m.EnumType); Prevention
- When defining an enum-typed contract member, always set the enumType parameter.
- Add a contract validation pass in EngineContractCatalog that checks all enum members have types.
- Use named arguments in the EngineContractMember constructor to avoid positional argument confusion.
When it happens
Trigger: An EngineContractMember is constructed with kind='enum' but enumType=null. CreateEnumValue at line 442 throws. This is a generator-level contract definition bug, not a locale YAML problem.
Common situations: Defining a new contract member for an enum-backed property and forgetting to set the EnumType parameter. Refactoring a member from string to enum without adding the enum type name. A positional argument mismatch in the constructor call shifting values.
Related errors
- Unsupported number-to-words contract member kind '{member.Ki
- Builder members require a builder name.
- Unexpected east-asian scale builder.
- Unsupported number-to-words builder '{member.Builder}'.
- Array-backed metric scale word contracts require a value pro
AI-assisted analysis of Humanizr/Humanizer@ffc2b77c0f (2026-08-13).
Data as JSON: /api/errors/1d22838254668c71.
Report an issue: GitHub.