{"record":{"id":"11f82df4301f0d06","repo":"Humanizr/Humanizer","slug":"inflection-source-entry-key-optionalproperty","errorCode":null,"errorMessage":"Inflection source '{entry.Key}' {optionalProperty} must be a non-empty scalar.","messagePattern":"Inflection source '(.+?)' (.+?) must be a non-empty scalar\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Humanizer.SourceGenerators/Generators/ProfileCatalogs/InflectionCatalogValidation.cs","lineNumber":130,"sourceCode":"                if (entry.Value is not SimpleYamlMapping source ||\n                    source.GetScalar(\"kind\") is not { Length: > 0 } ||\n                    source.GetScalar(\"locator\") is not { Length: > 0 })\n                {\n                    throw new InvalidOperationException(\n                        $\"Inflection source '{entry.Key}' must define non-empty kind and locator.\");\n                }\n\n                ValidateProperties(\n                    source,\n                    $\"Inflection source '{entry.Key}'\",\n                    \"kind\", \"locator\", \"revision\", \"credit\");\n                foreach (var optionalProperty in new[] { \"revision\", \"credit\" })\n                {\n                    if (source.TryGetValue(optionalProperty, out var optionalValue) &&\n                        (optionalValue is not SimpleYamlScalar optionalScalar ||\n                         string.IsNullOrWhiteSpace(optionalScalar.Value)))\n                    {\n                        throw new InvalidOperationException(\n                            $\"Inflection source '{entry.Key}' {optionalProperty} must be a non-empty scalar.\");\n                    }\n                }\n            }\n        }\n\n        static void ValidateTemplate(string ruleId, string template)\n        {\n            var marker = template.IndexOf(\"{stem}\", StringComparison.Ordinal);\n            var remainder = template.Replace(\"{stem}\", string.Empty);\n            if (marker < 0 ||\n                template.IndexOf(\"{stem}\", marker + \"{stem}\".Length, StringComparison.Ordinal) >= 0 ||\n                remainder.Contains('{') ||\n                remainder.Contains('}'))\n            {\n                throw new InvalidOperationException(\n                    $\"Inflection rule '{ruleId}' output must contain exactly one bounded '{{stem}}' placeholder.\");\n            }","sourceCodeStart":112,"sourceCodeEnd":148,"githubUrl":"https://github.com/Humanizr/Humanizer/blob/ffc2b77c0f30d2fb176875841424379319d0ae9b/src/Humanizer.SourceGenerators/Generators/ProfileCatalogs/InflectionCatalogValidation.cs#L112-L148","documentation":"The optional 'revision' and 'credit' fields on a source definition must be non-empty scalar strings when present. This is a secondary check after ValidateSourceDefinitions confirms kind/locator — it ensures that if a source opts into provenance detail fields, those fields carry real data rather than whitespace or empty strings.","triggerScenarios":"A source entry includes 'revision:' or 'credit:' but the value is not a SimpleYamlScalar or is a scalar containing only whitespace. For example, 'revision: \"\"' or 'credit:' with a null/empty value.","commonSituations":"Adding a placeholder 'revision:' key intending to fill it later. Copying a source template and leaving 'credit:' as an empty string. Accidentally indenting a value onto the next line so the scalar is empty.","solutions":["Fill the 'revision' or 'credit' field with a meaningful non-empty string value.","Remove the empty 'revision' or 'credit' key entirely if provenance detail is not needed — both are optional.","Ensure the value is a plain scalar, not a nested map or list."],"exampleFix":"# before\nsources:\n  custom1:\n    kind: 'dictionary'\n    locator: '...'\n    revision: ''\n# after\nsources:\n  custom1:\n    kind: 'dictionary'\n    locator: '...'\n    revision: '2024-03-15'","handlingStrategy":"validation","validationCode":"# Before building, verify revision/credit fields are non-empty scalars when present.\npython3 -c \"\nimport yaml, sys\nfor f in sys.argv[1:]:\n    d = yaml.safe_load(open(f))\n    sources = (d.get('inflection',{}).get('sources') or {})\n    for sid, sdef in sources.items():\n        if not isinstance(sdef, dict): continue\n        for opt in ('revision','credit'):\n            if opt in sdef:\n                val = sdef[opt]\n                if not isinstance(val, str) or not val.strip():\n                    print(f'{f}: source {sid!r} {opt} must be non-empty scalar')\n\" src/Humanizer/Locales/*.yml","typeGuard":null,"tryCatchPattern":null,"preventionTips":["If revision/credit are not yet known, omit the keys entirely rather than leaving empty strings.","Treat source definitions as complete records — fill all fields or remove optional ones.","Add a lint rule that flags empty-string values for optional provenance fields."],"tags":["inflection","source-generator","sources","provenance","yaml","build-time"],"backgroundTag":null,"analyzedSha":"ffc2b77c0f30d2fb176875841424379319d0ae9b","analyzedAt":"2026-08-13T21:42:34.584Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}