{"record":{"id":"b50f91b8eed76764","repo":"egametang/ET","slug":"config-factory-not-found-configtype-fullname","errorCode":null,"errorMessage":"config factory not found: {configType.FullName}","messagePattern":"config factory not found: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"Packages/cn.etetet.loader/Scripts/Loader/Share/ConfigLoaderHelper.cs","lineNumber":167,"sourceCode":"            {\n                throw new Exception($\"config interface invalid: {configType.FullName}\");\n            }\n\n            loadedConfigs.Add(configType, iConfig);\n            return singleton;\n        }\n\n        private static string GetConfigGroup(MemberInfo factoryType)\n        {\n            ConfigGroupAttribute configGroupAttribute = factoryType.GetCustomAttribute<ConfigGroupAttribute>();\n            return string.IsNullOrWhiteSpace(configGroupAttribute?.Name) ? ConfigGroupNames.Config : configGroupAttribute.Name;\n        }\n\n        private static IConfigFactory GetConfigFactory(Type configType, ConfigFactoryGroupCollection configFactories)\n        {\n            if (!configFactories.TryGetFactories(configType, out Dictionary<string, IConfigFactory> groupFactories))\n            {\n                throw new Exception($\"config factory not found: {configType.FullName}\");\n            }\n\n            List<string> activeGroups = GetActiveConfigGroups();\n            IConfigFactory match = null;\n            string matchedGroup = null;\n            foreach (string activeGroup in activeGroups)\n            {\n                if (!groupFactories.TryGetValue(activeGroup, out IConfigFactory factory))\n                {\n                    continue;\n                }\n\n                if (match != null)\n                {\n                    throw new Exception(\n                        $\"config factory group ambiguous: {configType.FullName}, matched groups: {matchedGroup}, {activeGroup}\");\n                }\n","sourceCodeStart":149,"sourceCodeEnd":185,"githubUrl":"https://github.com/egametang/ET/blob/5cab01f7a8bee5f49f4781eebe9e2b1c6d7ebe0f/Packages/cn.etetet.loader/Scripts/Loader/Share/ConfigLoaderHelper.cs#L149-L185","documentation":"Thrown by GetConfigFactory when no factory was ever registered for the requested configType. LoadOneConfig resolved the type and its ConfigProcessAttribute (Code), then asked for a factory, but ConfigFactoryGroupCollection has no entry keyed by that Type. This means the type is recognized as a code-config but no IConfigFactory targets it.","triggerScenarios":"A config category type carries ConfigProcessAttribute(Code) and reaches LoadOneConfig, but CreateConfigFactories never found/registered an IConfigFactory whose ConfigType equals it. Either the factory class is missing, was filtered out (abstract/interface), or its ConfigType points elsewhere.","commonSituations":"A new config category was added with its attribute but the matching factory wasn't generated; the factory exists in an assembly not scanned by CodeTypes; the factory is abstract and was skipped by the IsAbstract filter (line 95).","solutions":["Ensure an IConfigFactory with ConfigType == the named category exists, is concrete, and is in a scanned assembly.","If using codegen, regenerate factories for the new category.","Confirm the factory's assembly is included in CodeTypes' type scan."],"exampleFix":"// before — category declared but no factory\n[ConfigProcess(ConfigType.Code)]\npublic class NewConfigCategory : ASingleton, IConfig { ... }\n// (no NewConfigCategoryFactory anywhere)\n\n// after — add the factory\npublic class NewConfigCategoryFactory : IConfigFactory\n{\n    public Type ConfigType => typeof(NewConfigCategory);\n    public object Create() => new NewConfigCategory();\n}","handlingStrategy":"validation","validationCode":"// Pre-flight: ensure every Code config type has a registered factory\nvar factoryTypes = allTypes.Where(t => typeof(IConfigFactory).IsAssignableFrom(t) && !t.IsAbstract && !t.IsInterface);\nvar factoryTargets = factoryTypes.Select(t => ((IConfigFactory)Activator.CreateInstance(t)).ConfigType).ToHashSet();\nforeach (var ct in GetConfigTypes().Where(IsCodeConfig))\n    if (!factoryTargets.Contains(ct)) Log.Error($\"no factory for code config {ct.FullName}\");","typeGuard":"static bool HasFactory(Type configType, IEnumerable<Type> factoryTypes) =>\n    factoryTypes.Any(ft => ((IConfigFactory)Activator.CreateInstance(ft)).ConfigType == configType);","tryCatchPattern":null,"preventionTips":["Regenerate factories whenever a new config category is added.","Ensure factory assemblies are included in CodeTypes' scan.","Add a startup test that fails if any Code config lacks a factory."],"tags":["loader","config","factory","missing","registration","startup"],"backgroundTag":null,"analyzedSha":"5cab01f7a8bee5f49f4781eebe9e2b1c6d7ebe0f","analyzedAt":"2026-08-13T21:10:40.377Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}