Humanizr/Humanizer · error · InvalidOperationException

Locale '{localeCode}.{path}' keys must be between 0 and 59.

Error message

Locale '{localeCode}.{path}' keys must be between 0 and 59. Invalid key '{entry.Key}'.

What it means

Sparse minuteWordsMap keys must be between 0 and 59 inclusive (CanonicalLocaleAuthoring.cs:322-326). Values outside that range have no clock-minute meaning.

Source

Thrown at src/Humanizer.SourceGenerators/Common/CanonicalLocaleAuthoring.cs:324

        {
            if (!mapping.DuplicateKeys.IsDefaultOrEmpty)
            {
                throw new InvalidOperationException(
                    $"Locale '{localeCode}.{path}' defines duplicate key '{mapping.DuplicateKeys[0]}'.");
            }

            var normalizedValues = ImmutableDictionary.CreateBuilder<string, SimpleYamlValue>(StringComparer.Ordinal);
            foreach (var entry in mapping.Values)
            {
                if (!int.TryParse(entry.Key, NumberStyles.Integer, CultureInfo.InvariantCulture, out var minute))
                {
                    throw new InvalidOperationException(
                        $"Locale '{localeCode}.{path}' requires integer keys. Invalid key '{entry.Key}'.");
                }

                if (minute is < 0 or > 59)
                {
                    throw new InvalidOperationException(
                        $"Locale '{localeCode}.{path}' keys must be between 0 and 59. Invalid key '{entry.Key}'.");
                }

                var canonicalKey = minute.ToString(CultureInfo.InvariantCulture);
                if (normalizedValues.ContainsKey(canonicalKey))
                {
                    throw new InvalidOperationException(
                        $"Locale '{localeCode}.{path}' defines duplicate numeric minute slot {minute}.");
                }

                ValidateMinuteWordValue(localeCode, path, entry.Key, entry.Value, allowEmpty: false);
                normalizedValues[canonicalKey] = entry.Value;
            }

            return new SimpleYamlMapping(normalizedValues.ToImmutable());
        }

        static void ValidateMinuteWordValue(

View on GitHub (pinned to ffc2b77c0f)

Solutions

  1. Change the key to a valid minute in 0-59.
  2. Remove the out-of-range entry if it was a mistake.
  3. Rebuild.

Example fix

# before
surfaces:
  clock:
    minuteWordsMap:
      60: "top of the hour"
# after
surfaces:
  clock:
    minuteWordsMap:
      0: "top of the hour"
Defensive patterns

Strategy: validation

Validate before calling

import yaml, sys
doc = yaml.safe_load(open(sys.argv[1], encoding='utf-8'))
m = ((doc.get('surfaces') or {}).get('clock') or {}).get('minuteWordsMap')
if isinstance(m, dict):
    for k in m:
        n = int(k)
        assert 0 <= n <= 59, f'minuteWordsMap key {k} out of range 0-59'

Prevention

When it happens

Trigger: A key like `60:`, `120:`, or `-5:` in the sparse mapping.

Common situations: Mis-typing a value; confusing seconds (0-59 is shared with minutes) and adding a 60+ entry.

Related errors


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