Humanizr/Humanizer · error · InvalidOperationException
Unsupported conjunctional-scale strategy.
Error message
Unsupported conjunctional-scale strategy.
What it means
The ShouldAddAnd switch over profile.AndStrategy hit its default arm, meaning the profile declared a ConjunctionalScaleAndStrategy enum value the converter does not recognize. This is a locale-profile / source-generator defect, not bad user input: the YAML/generated profile named a conjunction strategy with no matching case branch. It fires on any cardinal or ordinal conversion for a ConjunctionalScale locale (English-family: en, en-GB, en-IN, etc.) when addAnd is true.
Source
Thrown at src/Humanizer/Localisation/NumberToWords/ConjunctionalScaleNumberToWordsConverter.cs:221
return $"{profile.OrdinalWholePhrasePrefix}{ConvertCore(number, isOrdinal: false, addAnd)}";
}
string GetUnitValue(long number, bool isOrdinal) =>
isOrdinal ? profile.OrdinalUnitsMap[number] : profile.UnitsMap[number];
// "and" placement is modeled as a structural rule family rather than as locale branches.
// The generated profile says which insertion points are legal, and this method translates that
// choice into the current local context: inside a hundred group, after a higher scale, both, or neither.
bool ShouldAddAnd(bool addAnd, bool hasHundreds, bool hasScalePrefix, bool isTerminalScaleRemainder) =>
addAnd && profile.AndStrategy switch
{
ConjunctionalScaleAndStrategy.WithinGroupAndAfterScaleSubHundredRemainder => hasHundreds || hasScalePrefix,
ConjunctionalScaleAndStrategy.WithinGroupOnly => hasHundreds,
ConjunctionalScaleAndStrategy.AfterScaleSubHundredRemainderOnly => !hasHundreds && hasScalePrefix,
ConjunctionalScaleAndStrategy.WithinGroupAndTerminalScaleSubHundredRemainder => hasHundreds || (hasScalePrefix && isTerminalScaleRemainder),
ConjunctionalScaleAndStrategy.Never => false,
_ => throw new InvalidOperationException("Unsupported conjunctional-scale strategy.")
};
void ApplyOrdinalLeadingOneStrategy(List<string> parts, bool isOrdinal)
{
if (!isOrdinal || profile.OrdinalLeadingOneStrategy != ConjunctionalScaleOrdinalLeadingOneStrategy.OmitLeadingOne || parts.Count == 0)
{
return;
}
if (parts[0] == profile.UnitsMap[1])
{
parts.RemoveAt(0);
return;
}
if (parts[0].StartsWith(profile.UnitsMap[1] + " ", StringComparison.Ordinal))
{
parts[0] = parts[0][profile.UnitsMap[1].Length..].TrimStart();View on GitHub (pinned to ffc2b77c0f)
Solutions
- Report the locale + Humanizer version — this is a library/locale-data bug requiring a switch case or corrected profile data.
- Use a consistent Humanizer version where the profile data and the switch agree.
- If authoring a locale, set AndStrategy to one of WithinGroupAndAfterScaleSubHundredRemainder, WithinGroupOnly, AfterScaleSubHundredRemainderOnly, WithinGroupAndTerminalScaleSubHundredRemainder, or Never.
Defensive patterns
Strategy: try-catch
Validate before calling
// AndStrategy is internal profile data; callers cannot pre-validate it. The only signal is the // InvalidOperationException at conversion time. Wrap converter resolution + Convert together.
Try / catch
string words;
try
{
words = value.ToWords(culture);
}
catch (InvalidOperationException ex) when (ex.Message.Contains("conjunctional-scale strategy"))
{
// Profile/locale-data defect; fall back to a known-good culture.
words = value.ToWords(CultureInfo.InvariantCulture);
} Prevention
- Pin a Humanizer version where the locale profile and the switch agree.
- Smoke-test ToWords for each locale you ship after any Humanizer upgrade.
- Report locale-data defects upstream rather than compensating in application code.
When it happens
Trigger: Any ToWords()/ToOrdinalWords() call (with addAnd true, the default) for a ConjunctionalScale locale whose profile.AndStrategy is an enum value outside the five handled cases.
Common situations: After a Humanizer version upgrade that introduced a new ConjunctionalScaleAndStrategy member without updating the switch; a hand-edited or stale generated profile carrying an out-of-range enum value.
Related errors
- Unsupported harmony-ordinal suffix strategy.
- Harmony-ordinal suffix data is missing.
- Harmony-ordinal membership suffix data is incomplete.
- The scale profile must include the thousand row.
- Indian scale-form number profiles require a scale value no g
AI-assisted analysis of Humanizr/Humanizer@ffc2b77c0f (2026-08-13).
Data as JSON: /api/errors/03b6dd019ae87a1c.
Report an issue: GitHub.