Humanizr/Humanizer · error · InvalidOperationException
Locale '{parsedLocale.LocaleCode}' is defined more than once
Error message
Locale '{parsedLocale.LocaleCode}' is defined more than once. What it means
Thrown by LocaleCatalogInput.Create when two locale files resolve to the same LocaleCode (the file name without extension under src/Humanizer/Locales). Each locale code must be defined exactly once across the whole Locales tree. Surfaced as compiler diagnostic HSG003 (severity Error).
Source
Thrown at src/Humanizer.SourceGenerators/Common/LocaleYamlCatalog.cs:97
public static LocaleCatalogInput Create(ImmutableArray<LocaleDefinitionFile?> files)
{
var diagnostics = ImmutableArray.CreateBuilder<Diagnostic>();
var parsedLocales = new Dictionary<string, LocaleDefinition>(StringComparer.Ordinal);
foreach (var file in files)
{
if (file is null)
{
continue;
}
try
{
var parsedLocale = ParseLocaleDefinition(file.LocaleCode, file.FileText);
if (parsedLocales.ContainsKey(parsedLocale.LocaleCode))
{
throw new InvalidOperationException($"Locale '{parsedLocale.LocaleCode}' is defined more than once.");
}
parsedLocales[parsedLocale.LocaleCode] = parsedLocale;
}
catch (Exception exception)
{
diagnostics.Add(Diagnostic.Create(
HumanizerSourceGenerator.Diagnostics.InvalidLocaleDefinition,
Location.None,
file.LocaleCode,
exception.Message));
}
}
// Resolve inheritance once at the catalog boundary so every downstream generator sees a
// fully merged locale payload instead of reimplementing merge semantics independently.
// That keeps supported locale variants on the localized parent chain instead of
// allowing each generator to guess its own fallback behavior.View on GitHub (pinned to ffc2b77c0f)
Solutions
- Locate both files matching the locale code reported in the message and remove or rename one.
- Ensure backup/scratch files do not use the .yml extension (the generator only loads .yml files under Locales).
- On case-insensitive filesystems, verify the on-disk casing matches the intended code exactly once.
- Rebuild to confirm the HSG003 diagnostic clears.
Example fix
# before: two files both resolve to locale code 'fr' # src/Humanizer/Locales/fr.yml # src/Humanizer/Locales/wip/fr.yml # after: keep one # src/Humanizer/Locales/fr.yml # (delete src/Humanizer/Locales/wip/fr.yml or rename it to the intended new code)
Defensive patterns
Strategy: validation
Validate before calling
# List locale codes derived from file names and flag duplicates. find src/Humanizer/Locales -name '*.yml' -printf '%f\n' | sed 's/\.yml$//' | sort | uniq -d # Also catch stray .yml backups: find src/Humanizer/Locales -name '*.yml*' -type f
Prevention
- Name each locale file exactly once with its BCP-47 code; never duplicate across subfolders.
- Keep backups outside the Locales tree or with a non-.yml extension.
- On case-insensitive filesystems, double-check casing matches the intended code.
When it happens
Trigger: Adding a new file whose name collides with an existing locale (e.g. a second fr.yml in a different subfolder, or a copy fr.yml.bak that is also picked up), or two files differing only by case on a case-insensitive filesystem.
Common situations: Copy-paste to start a new locale and forgetting to rename the file; backup files with .yml extension left in the tree; case-collision on macOS/Windows checkouts; merge bringing in a duplicate.
Related errors
- Phrase '{path}' must define forms, 'symbol', or 'template'.
- Phrase '{path}' must define forms.
- Phrase '{path}' must define 'numeric', 'text', or 'words'.
- Phrase forms '{path}' must define at least one form.
- Phrase '{path}.countPlacement' uses unsupported count placem
AI-assisted analysis of Humanizr/Humanizer@ffc2b77c0f (2026-08-13).
Data as JSON: /api/errors/fde4bd3ab075ad3c.
Report an issue: GitHub.