Humanizr/Humanizer · error · InvalidOperationException

Missing required string property '{member.SourcePath}'.

Error message

Missing required string property '{member.SourcePath}'.

What it means

For a contract member of kind 'string', the factory tries to resolve the value from the primary source path, then the fallback source path, then the default value. If all three are absent, GetStringValue throws because it has no value to emit in the generated constructor call. This typically means the locale YAML is missing a required property.

Source

Thrown at src/Humanizer.SourceGenerators/Generators/ProfileCatalogs/NumberToWordsEngineContractFactory.cs:557

        static string GetStringValue(JsonElement root, EngineContractMember member)
        {
            if (EngineContractUtilities.TryGetOptionalString(root, member.SourcePath, out var value))
            {
                return value!;
            }

            if (member.FallbackSourcePath is not null && EngineContractUtilities.TryGetOptionalString(root, member.FallbackSourcePath, out var fallback))
            {
                return fallback!;
            }

            if (member.DefaultValue is not null)
            {
                return member.DefaultValue;
            }

            throw new InvalidOperationException($"Missing required string property '{member.SourcePath}'.");
        }

        static string? GetOptionalStringValue(JsonElement root, EngineContractMember member)
        {
            if (EngineContractUtilities.TryGetOptionalString(root, member.SourcePath, out var value))
            {
                return value;
            }

            if (member.FallbackSourcePath is not null && EngineContractUtilities.TryGetOptionalString(root, member.FallbackSourcePath, out var fallback))
            {
                return fallback;
            }

            return member.DefaultValue;
        }

        static bool GetBooleanValue(JsonElement root, EngineContractMember member)

View on GitHub (pinned to ffc2b77c0f)

Solutions

  1. Add the missing YAML property to the locale file at the path specified in the error message (member.SourcePath).
  2. If the property is optional, set a DefaultValue on the EngineContractMember so absent values fall back gracefully.
  3. If the property was renamed, update either the contract's SourcePath or the locale YAML to match.

Example fix

# before (fr.yml — missing millionSingularWord)
numberToWords:
  engine: 'billion-strategy'
  cardinal:
    billionStrategy: 'billion-word'
# after
numberToWords:
  engine: 'billion-strategy'
  cardinal:
    millionSingularWord: 'million'
    millionPluralWord: 'millions'
    billionStrategy: 'billion-word'
    billionSingularWord: 'milliard'
    billionPluralWord: 'milliards'
Defensive patterns

Strategy: validation

Validate before calling

# Before building, verify required string properties exist in the locale YAML for each engine.
python3 -c "
import yaml, sys
# Map engine -> required root-level properties (simplified; extend per engine)
required = {
    'billion-strategy': ['cardinal.millionSingularWord','cardinal.millionPluralWord','cardinal.billionStrategy'],
}
for f in sys.argv[1:]:
    d = yaml.safe_load(open(f))
    n2w = d.get('numberToWords') or {}
    engine = n2w.get('engine')
    for path in required.get(engine,[]):
        obj = n2w
        for part in path.split('.'):
            obj = (obj or {}).get(part)
            if obj is None: break
        if obj is None:
            print(f'{f}: engine {engine!r} missing required property {path}')
" src/Humanizer/Locales/*.yml

Prevention

When it happens

Trigger: An EngineContractMember with kind='string' (or kind='enum' which delegates to GetStringValue) has no value at SourcePath in the locale YAML, no FallbackSourcePath, and no DefaultValue configured. The method exhausts all resolution options and throws.

Common situations: A locale YAML omits a required property that the engine contract expects (e.g., 'millionSingularWord' for a billion-strategy engine). Adding a new required string member to a contract without providing a default, breaking locales that don't define it. Renaming a YAML property without updating existing locales.

Related errors


AI-assisted analysis of Humanizr/Humanizer@ffc2b77c0f (2026-08-13). Data as JSON: /api/errors/6436b71901a3cdd8. Report an issue: GitHub.