{"record":{"id":"7db2969886e18118","repo":"egametang/ET","slug":"config-group-is-empty-factory-gettype-fullname","errorCode":null,"errorMessage":"config group is empty: {factory.GetType().FullName}","messagePattern":"config group is empty: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"Packages/cn.etetet.loader/Scripts/Loader/Share/ConfigLoaderHelper.cs","lineNumber":20,"sourceCode":"using System.Collections.Generic;\nusing System.Reflection;\n\nnamespace ET\n{\n    public sealed class ConfigFactoryGroupCollection\n    {\n        private readonly Dictionary<Type, Dictionary<string, IConfigFactory>> factories = new();\n\n        public void Add(string configGroup, IConfigFactory factory)\n        {\n            if (factory.ConfigType == null)\n            {\n                throw new Exception($\"config factory target is null: {factory.GetType().FullName}\");\n            }\n\n            if (string.IsNullOrWhiteSpace(configGroup))\n            {\n                throw new Exception($\"config group is empty: {factory.GetType().FullName}\");\n            }\n\n            if (!this.factories.TryGetValue(factory.ConfigType, out Dictionary<string, IConfigFactory> groupFactories))\n            {\n                groupFactories = new Dictionary<string, IConfigFactory>(StringComparer.Ordinal);\n                this.factories.Add(factory.ConfigType, groupFactories);\n            }\n\n            if (!groupFactories.TryAdd(configGroup, factory))\n            {\n                throw new Exception($\"duplicate config factory: {factory.ConfigType.FullName} group={configGroup}\");\n            }\n        }\n\n        public bool TryGetFactories(Type configType, out Dictionary<string, IConfigFactory> groupFactories)\n        {\n            return this.factories.TryGetValue(configType, out groupFactories);\n        }","sourceCodeStart":2,"sourceCodeEnd":38,"githubUrl":"https://github.com/egametang/ET/blob/5cab01f7a8bee5f49f4781eebe9e2b1c6d7ebe0f/Packages/cn.etetet.loader/Scripts/Loader/Share/ConfigLoaderHelper.cs#L2-L38","documentation":"Thrown by ConfigFactoryGroupCollection.Add when the configGroup argument is null/empty/whitespace. The group name selects which variant of a factory is active (e.g. Config vs a StartConfig override); an empty group is ambiguous and cannot be keyed in the inner Dictionary, so Add rejects it. The group is derived from the factory type's ConfigGroupAttribute (GetConfigGroup), defaulting to ConfigGroupNames.Config when absent.","triggerScenarios":"CreateConfigFactories calls Add(GetConfigGroup(factoryType), factory). GetConfigGroup returns the ConfigGroupAttribute.Name; if that attribute exists but its Name is explicitly empty/whitespace (and thus is NOT replaced by the default, because the default only applies when the attribute is null/missing), Add throws.","commonSituations":"A developer added [ConfigGroup(\"\")] or [ConfigGroup(\" \")] to a factory thinking it means 'default'; a codegen template emitted an empty Name.","solutions":["Remove the empty ConfigGroupAttribute so GetConfigGroup falls back to ConfigGroupNames.Config, OR set a real group name.","If a custom default is desired, fix GetConfigGroup to treat empty as the default rather than passing it through."],"exampleFix":"// before\n[ConfigGroup(\"\")]\npublic class MyFactory : IConfigFactory { }\n\n// after — either omit the attribute or set a real name\npublic class MyFactory : IConfigFactory { } // falls back to ConfigGroupNames.Config","handlingStrategy":"validation","validationCode":"// Defensive: normalize empty group to the default before calling Add\nstring group = string.IsNullOrWhiteSpace(configGroup) ? ConfigGroupNames.Config : configGroup;\nfactories.Add(group, factory);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never use [ConfigGroup(\"\")]; omit the attribute to get the default.","Audit ConfigGroupAttribute usages for empty names.","Consider making GetConfigGroup treat empty Name as missing."],"tags":["loader","config","factory","configgroup","attribute"],"backgroundTag":null,"analyzedSha":"5cab01f7a8bee5f49f4781eebe9e2b1c6d7ebe0f","analyzedAt":"2026-08-13T21:10:40.377Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}