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

  1. Locate both files matching the locale code reported in the message and remove or rename one.
  2. Ensure backup/scratch files do not use the .yml extension (the generator only loads .yml files under Locales).
  3. On case-insensitive filesystems, verify the on-disk casing matches the intended code exactly once.
  4. 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

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


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