Humanizr/Humanizer · error · InvalidOperationException

'{path}.sameAsNominative' must be true.

Error message

'{path}.sameAsNominative' must be true.

What it means

When a duration-case unit declares 'sameAsNominative', ParseUnit (DurationCaseModels.cs:1159-1162) requires the value to be exactly boolean true. The schema has no false branch: a unit either is identical to the nominative (true) or it carries a full phrase. Any other value (false, "yes", 1, a non-boolean string) fails bool.TryParse or the enabled check.

Source

Thrown at src/Humanizer.SourceGenerators/Common/DurationCaseModels.cs:1161

            return new DurationCaseOverlay(units.ToImmutable());
        }

        static DurationCaseUnit ParseUnit(SimpleYamlValue value, string path)
        {
            if (ContainsInheritanceMarker(value))
            {
                throw new InvalidOperationException(
                    $"'{path}' contains an unresolved CLDR inheritance marker.");
            }

            var mapping = ExpectMapping(value, path);
            if (mapping.GetScalar("sameAsNominative") is { } sameAsNominative)
            {
                RejectUnknownKeys(mapping, path, ["sameAsNominative"]);
                if (!bool.TryParse(sameAsNominative, out var enabled) || !enabled)
                {
                    throw new InvalidOperationException($"'{path}.sameAsNominative' must be true.");
                }

                return new DurationCaseUnit(DurationCaseUnitKind.SameAsNominative, null);
            }

            if (mapping.GetScalar("unsupported") is { } unsupported)
            {
                RejectUnknownKeys(mapping, path, ["unsupported"]);
                if (!bool.TryParse(unsupported, out var enabled) || !enabled)
                {
                    throw new InvalidOperationException($"'{path}.unsupported' must be true.");
                }

                return new DurationCaseUnit(DurationCaseUnitKind.Unsupported, null);
            }

            var phrase = LocalePhraseNormalization.ParseTimeSpanPhrase(value, path);
            if (phrase.Single is null ||

View on GitHub (pinned to ffc2b77c0f)

Solutions

  1. If the unit really equals the nominative form, set 'sameAsNominative: true' (unquoted YAML boolean).
  2. If it differs, delete the sameAsNominative key and author a full phrase: block (single + multiple.forms).
  3. Ensure the value is a plain YAML boolean, not a quoted string.

Example fix

# before
millisecond:
  sameAsNominative: false
# after - unit differs from nominative
millisecond:
  phrase:
    single: { numeric: '1 millisekunda', words: 'jedna millisekunda' }
    multiple:
      forms: { default: 'millisekund' }
Defensive patterns

Strategy: validation

Validate before calling

# A sameAsNominative unit must be exactly true
foreach ($u in $caseUnits.GetEnumerator()) {
    if ($u.Value -is [hashtable] -and $u.Value.ContainsKey('sameAsNominative') `
        -and $u.Value.sameAsNominative -ne $true) {
        throw "unit '$($u.Key)': sameAsNominative must be true (got $($u.Value.sameAsNominative))"
    }
}

Prevention

When it happens

Trigger: sameAsNominative is set to false, to a quoted string like "yes"/"true", or to a non-boolean scalar.

Common situations: A contributor writes 'sameAsNominative: false' meaning 'not the same' — but the correct action is to remove the key and author a phrase; or a typo from copy-paste.

Related errors


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