Humanizr/Humanizer · critical · InvalidOperationException

Locale '{localeCode}.{path}.{key}' must be a string.

Error message

Locale '{localeCode}.{path}.{key}' must be a string.

What it means

Thrown by ValidateMinuteWordValue when a clock minute slot's value is not a YAML scalar string (it is a mapping, a sequence, or a non-string token). The minute-words table must map each integer key to a single human-readable string, so any structured value is rejected at build time.

Source

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

                }

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

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

        static void ValidateMinuteWordValue(
            string localeCode,
            string path,
            string key,
            SimpleYamlValue value,
            bool allowEmpty)
        {
            if (value is not SimpleYamlScalar scalar || !scalar.IsString)
            {
                throw new InvalidOperationException(
                    $"Locale '{localeCode}.{path}.{key}' must be a string.");
            }

            if (!allowEmpty && string.IsNullOrEmpty(scalar.Value))
            {
                throw new InvalidOperationException(
                    $"Locale '{localeCode}.{path}.{key}' must be a non-empty string. Omit unused sparse slots instead.");
            }
        }

        static void ValidateNumberFormattingBlock(string localeCode, SimpleYamlMapping formatting)
        {
            foreach (var property in formatting.Values.Keys.Where(static property => property is not ("decimalSeparator" or "negativeSign" or "groupSeparator")))
            {
                throw new InvalidOperationException(
                    $"Locale '{localeCode}.surfaces.number.formatting' defines unsupported property '{property}'. Supported properties: decimalSeparator, negativeSign, groupSeparator.");
            }

View on GitHub (pinned to ffc2b77c0f)

Solutions

  1. Replace the minute's value with a single inline string scalar, e.g. '5: five minutes'.
  2. Check indentation: the minute key and its value must sit on the same line or be a plain folded scalar, not a nested block.
  3. Re-run 'dotnet build' to confirm ValidateMinuteWordValue no longer fires for {path}.{key}.

Example fix

# before
minutes:
  5:
    word: five minutes
# after
minutes:
  5: five minutes
Defensive patterns

Strategy: validation

Validate before calling

# Ensure every minute value is a plain scalar, not a nested mapping/sequence.
# In your editor, each line under 'minutes:' must read '<int>: <string>'.

Prevention

When it happens

Trigger: A locale YAML minute entry is indented as a nested mapping/sequence (e.g. '5:\n value: five') or is a quoted multi-line block, so SimpleYamlValue is not a SimpleYamlScalar with IsString. Detected at CanonicalLocaleAuthoring.cs:349-353.

Common situations: Pasting from a richer locale format that nests metadata under each minute; mis-indenting a YAML value so it becomes a child mapping; converting an array-based locale representation into the canonical mapping form.

Related errors


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