{"record":{"id":"32e02eaf7e1a5aaf","repo":"Humanizr/Humanizer","slug":"failed-to-project-metric-scale-words-for-locale","errorCode":null,"errorMessage":"Failed to project metric scale words for locale '{locale.LocaleCode}' using engine '{profile.Engine}': {exception.Message}","messagePattern":"Failed to project metric scale words for locale '(.+?)' using engine '(.+?)': (.+?)","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Humanizer.SourceGenerators/Generators/ProfileCatalogs/MetricScaleWordCatalogInput.cs","lineNumber":41,"sourceCode":"                            locale.LocaleCode,\n                            ImmutableArray<MetricScaleWordDefinition>.Empty);\n                    }\n\n                    var profile = new NumberToWordsProfileDefinition(\n                        feature.ProfileName!,\n                        GetRequiredString(feature.ProfileRoot, \"engine\"),\n                        feature.ProfileRoot);\n                    try\n                    {\n                        return new MetricScaleWordProfileDefinition(\n                            locale.LocaleCode,\n                            NumberToWordsEngineContractFactory.CreateMetricScaleWords(\n                                profile,\n                                EngineContractCatalog.NumberToWords));\n                    }\n                    catch (Exception exception)\n                    {\n                        throw new InvalidOperationException(\n                            $\"Failed to project metric scale words for locale '{locale.LocaleCode}' \" +\n                            $\"using engine '{profile.Engine}': {exception.Message}\",\n                            exception);\n                    }\n                })\n                .Where(static profile => !profile.ScaleWords.IsDefaultOrEmpty)\n                .ToImmutableArray();\n\n            return new(profiles);\n        }\n\n        public void Emit(SourceProductionContext context)\n        {\n            var builder = new StringBuilder();\n            builder.AppendLine(\"#nullable enable\");\n            builder.AppendLine(\"namespace Humanizer;\");\n            builder.AppendLine();\n            builder.AppendLine(\"static partial class LocalizedMetricScaleWordCatalog\");","sourceCodeStart":23,"sourceCodeEnd":59,"githubUrl":"https://github.com/Humanizr/Humanizer/blob/ffc2b77c0f30d2fb176875841424379319d0ae9b/src/Humanizer.SourceGenerators/Generators/ProfileCatalogs/MetricScaleWordCatalogInput.cs#L23-L59","documentation":"When the source generator builds metric scale word profiles for each locale, it wraps any exception from CreateMetricScaleWords in an InvalidOperationException that includes the locale code, engine name, and original exception message. This is a context-enrichment wrapper — the inner exception carries the root cause, and this message tells you which locale and engine triggered it.","triggerScenarios":"Any exception thrown inside NumberToWordsEngineContractFactory.CreateMetricScaleWords for a locale that uses a generated number-to-words profile. The catch at line 39 wraps and rethrows with locale/engine context. The inner exception is typically one of errors 253-259.","commonSituations":"Editing a locale's numberToWords YAML block and introducing a structural error (missing property, unknown builder, bad contract member). Upgrading Humanizer and a locale's engine contract changed shape. Adding a new locale with an incomplete numberToWords section.","solutions":["Read the full exception message including the inner exception — the root cause is in exception.Message after the colon.","Fix the underlying issue in the locale YAML identified by the inner exception (e.g., missing property, unknown builder).","Temporarily set the locale's numberToWords profile to not use a generated profile to isolate whether the metric scale word projection or the main profile is at fault."],"exampleFix":"# The error message format is:\n# \"Failed to project metric scale words for locale 'fr' using engine 'billion-strategy': <inner>\"\n# Fix the <inner> cause — e.g., if inner says \"Missing required string property 'millionSingularWord'\":\n# before (fr.yml)\nnumberToWords:\n  engine: 'billion-strategy'\n  cardinal:\n    scales: [...]\n# after\nnumberToWords:\n  engine: 'billion-strategy'\n  cardinal:\n    millionSingularWord: 'million'\n    millionPluralWord: 'millions'\n    billionStrategy: 'billion-word'\n    billionSingularWord: 'milliard'\n    billionPluralWord: 'milliards'","handlingStrategy":"validation","validationCode":"# Before building, validate the locale's numberToWords YAML can be projected.\n# Run a dry parse that exercises CreateMetricScaleWords logic paths:\npython3 -c \"\nimport yaml, sys\nfor f in sys.argv[1:]:\n    d = yaml.safe_load(open(f))\n    n2w = d.get('numberToWords') or {}\n    engine = n2w.get('engine')\n    if not engine: continue\n    print(f'{f}: engine={engine} — verify all required properties for this engine are present')\n\" src/Humanizer/Locales/*.yml","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always read the inner exception message in the build output — it names the exact property or contract issue.","When adding a new locale, start from a working locale with the same engine and adapt incrementally.","Build after each YAML change to catch metric scale word projection errors early."],"tags":["metric-scale-words","source-generator","number-to-words","locale","wrapper","build-time"],"backgroundTag":null,"analyzedSha":"ffc2b77c0f30d2fb176875841424379319d0ae9b","analyzedAt":"2026-08-13T21:42:34.584Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}