{"record":{"id":"431928a7f732ce6e","repo":"egametang/ET","slug":"create-config-factory-failed-factorytype-fullnam","errorCode":null,"errorMessage":"create config factory failed: {factoryType.FullName}","messagePattern":"create config factory failed: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"Packages/cn.etetet.loader/Scripts/Loader/Share/ConfigLoaderHelper.cs","lineNumber":114,"sourceCode":"                {\n                    continue;\n                }\n\n                if (!typeof(IConfigFactory).IsAssignableFrom(type))\n                {\n                    continue;\n                }\n\n                factoryTypes.Add(type);\n            }\n\n            factoryTypes.Sort((left, right) => string.CompareOrdinal(left.FullName, right.FullName));\n            ConfigFactoryGroupCollection factories = new();\n            foreach (Type factoryType in factoryTypes)\n            {\n                if (Activator.CreateInstance(factoryType) is not IConfigFactory factory)\n                {\n                    throw new Exception($\"create config factory failed: {factoryType.FullName}\");\n                }\n\n                factories.Add(GetConfigGroup(factoryType), factory);\n            }\n\n            return factories;\n        }\n\n        public static ASingleton LoadOneConfig(Type configType, ConfigFactoryGroupCollection configFactories, Dictionary<Type, IConfig> loadedConfigs)\n        {\n            ConfigProcessAttribute configProcessAttribute = configType.GetCustomAttributes(typeof(ConfigProcessAttribute), false)[0] as ConfigProcessAttribute;\n            if (configProcessAttribute.ConfigType != ConfigType.Code)\n            {\n                throw new Exception($\"unsupported config type: {configProcessAttribute.ConfigType} {configType.FullName}\");\n            }\n\n            IConfigFactory factory = GetConfigFactory(configType, configFactories);\n            object category = factory.Create();","sourceCodeStart":96,"sourceCodeEnd":132,"githubUrl":"https://github.com/egametang/ET/blob/5cab01f7a8bee5f49f4781eebe9e2b1c6d7ebe0f/Packages/cn.etetet.loader/Scripts/Loader/Share/ConfigLoaderHelper.cs#L96-L132","documentation":"Thrown by CreateConfigFactories when Activator.CreateInstance(factoryType) returns something that is NOT an IConfigFactory. The candidate type already passed the typeof(IConfigFactory).IsAssignableFrom filter (line 100), so in practice this throw means the instance was null — which Activator.CreateInstance returns only for nullable-value-type edge cases, or the constructor threw and was swallowed. More commonly it indicates a factory whose parameterless constructor is missing (Activator returns null for certain Nullable<T> scenarios) or a reflection/CLR quirk.","triggerScenarios":"A type implements IConfigFactory, is non-abstract and concrete, but its instantiation via Activator.CreateInstance does not yield a non-null IConfigFactory. Typically a missing public parameterless constructor causes a MissingMethodException earlier, so this specific throw points at a value-type/Nullable instantiation oddity or a constructor that returns null unexpectedly.","commonSituations":"A factory is a struct (ValueType) implementing IConfigFactory where the boxed 'is not IConfigFactory' pattern misbehaves; a factory whose constructor logic leaves it in an unusable state; an AOT/IL2CPP stripping issue removing the constructor.","solutions":["Ensure the factory is a class with a public parameterless constructor.","If it must be a struct, verify Activator.CreateInstance boxes correctly under the target runtime (test on IL2CPP/AOT).","Catch MissingMethodException separately to distinguish a missing constructor from this null-result case."],"exampleFix":"// before — struct factory, Activator edge case\npublic struct MyFactory : IConfigFactory { ... }\n\n// after — class with public parameterless ctor\npublic class MyFactory : IConfigFactory\n{\n    public MyFactory() { }\n    public Type ConfigType => typeof(MyConfigCategory);\n}","handlingStrategy":"validation","validationCode":"// Prefer classes with public parameterless ctors; assert at design time\nif (factoryType.IsValueType || factoryType.GetConstructor(Type.EmptyTypes) == null)\n    Log.Error($\"factory {factoryType.FullName} must be a class with a public parameterless ctor\");","typeGuard":"static bool IsInstantiableFactory(Type t) =>\n    !t.IsAbstract && !t.IsInterface && !t.IsValueType\n    && t.GetConstructor(Type.EmptyTypes) != null;","tryCatchPattern":null,"preventionTips":["Make config factories classes, not structs.","Ensure a public parameterless constructor on every factory.","Test factory instantiation under the target runtime (IL2CPP/AOT), not just editor/mono."],"tags":["loader","config","factory","reflection","activator","startup"],"backgroundTag":null,"analyzedSha":"5cab01f7a8bee5f49f4781eebe9e2b1c6d7ebe0f","analyzedAt":"2026-08-13T21:10:40.377Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}