{"record":{"id":"0b1bcb2655343971","repo":"egametang/ET","slug":"config-singleton-invalid-configtype-fullname","errorCode":null,"errorMessage":"config singleton invalid: {configType.FullName}","messagePattern":"config singleton invalid: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"Packages/cn.etetet.loader/Scripts/Loader/Share/ConfigLoaderHelper.cs","lineNumber":145,"sourceCode":"            {\n                throw new Exception($\"unsupported config type: {configProcessAttribute.ConfigType} {configType.FullName}\");\n            }\n\n            IConfigFactory factory = GetConfigFactory(configType, configFactories);\n            object category = factory.Create();\n            if (category == null)\n            {\n                throw new Exception($\"config create failed: {configType.FullName}\");\n            }\n\n            if (category.GetType() != configType)\n            {\n                throw new Exception($\"config type mismatch: expect={configType.FullName} actual={category.GetType().FullName}\");\n            }\n\n            if (category is not ASingleton singleton)\n            {\n                throw new Exception($\"config singleton invalid: {configType.FullName}\");\n            }\n\n            if (category is not IConfig iConfig)\n            {\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)","sourceCodeStart":127,"sourceCodeEnd":163,"githubUrl":"https://github.com/egametang/ET/blob/5cab01f7a8bee5f49f4781eebe9e2b1c6d7ebe0f/Packages/cn.etetet.loader/Scripts/Loader/Share/ConfigLoaderHelper.cs#L127-L163","documentation":"Thrown by LoadOneConfig when the created category object is not an ASingleton. The ET framework registers configs as singletons via World.ReplaceSingleton, so every code-config category must inherit ASingleton; if it only implements IConfig (or neither), it cannot be registered and the load aborts.","triggerScenarios":"A config category class implements IConfig but does not derive from ASingleton. LoadOneConfig's 'is not ASingleton' pattern (line 143) catches this after the type-equality check passes.","commonSituations":"A hand-written config category omitted the ASingleton base class; a codegen template generated a plain class; a refactor moved the category off the singleton hierarchy.","solutions":["Make the named config category derive from ASingleton (and still implement IConfig).","Update the codegen template so all config categories inherit ASingleton."],"exampleFix":"// before\npublic class MyConfigCategory : IConfig { ... }\n\n// after\npublic class MyConfigCategory : ASingleton, IConfig { ... }","handlingStrategy":"validation","validationCode":null,"typeGuard":"static bool IsCodeConfigCategory(Type t) =>\n    typeof(ASingleton).IsAssignableFrom(t) && typeof(IConfig).IsAssignableFrom(t);","tryCatchPattern":null,"preventionTips":["All code-config categories must derive from ASingleton.","Enforce via a codegen template and a build-time reflection check.","Document the required base+interface contract for config categories."],"tags":["loader","config","singleton","inheritance","codegen"],"backgroundTag":null,"analyzedSha":"5cab01f7a8bee5f49f4781eebe9e2b1c6d7ebe0f","analyzedAt":"2026-08-13T21:10:40.377Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}