egametang/ET · error

config type mismatch: expect={configType.FullName} actual={c

Error message

config type mismatch: expect={configType.FullName} actual={category.GetType().FullName}

What it means

Thrown by LoadOneConfig when the object returned by factory.Create() has a runtime Type that does not exactly equal the requested configType. The loader keys configs by their declared category Type, so a mismatch means the factory produced the wrong category — a wiring/codegen defect rather than a data problem.

Source

Thrown at Packages/cn.etetet.loader/Scripts/Loader/Share/ConfigLoaderHelper.cs:140

        public static ASingleton LoadOneConfig(Type configType, ConfigFactoryGroupCollection configFactories, Dictionary<Type, IConfig> loadedConfigs)
        {
            ConfigProcessAttribute configProcessAttribute = configType.GetCustomAttributes(typeof(ConfigProcessAttribute), false)[0] as ConfigProcessAttribute;
            if (configProcessAttribute.ConfigType != ConfigType.Code)
            {
                throw new Exception($"unsupported config type: {configProcessAttribute.ConfigType} {configType.FullName}");
            }

            IConfigFactory factory = GetConfigFactory(configType, configFactories);
            object category = factory.Create();
            if (category == null)
            {
                throw new Exception($"config create failed: {configType.FullName}");
            }

            if (category.GetType() != configType)
            {
                throw new Exception($"config type mismatch: expect={configType.FullName} actual={category.GetType().FullName}");
            }

            if (category is not ASingleton singleton)
            {
                throw new Exception($"config singleton invalid: {configType.FullName}");
            }

            if (category is not IConfig iConfig)
            {
                throw new Exception($"config interface invalid: {configType.FullName}");
            }

            loadedConfigs.Add(configType, iConfig);
            return singleton;
        }

        private static string GetConfigGroup(MemberInfo factoryType)
        {

View on GitHub (pinned to 5cab01f7a8)

Solutions

  1. Align the factory's ConfigType with the concrete type returned by Create() (they must be the same Type).
  2. If inheritance is intended, relax the exact-equality check to IsAssignableFrom — but only if the design permits.
  3. Re-run codegen so factory and category stay consistent.

Example fix

// before — ConfigType and Create() return type differ
public Type ConfigType => typeof(BaseCategory);
public object Create() => new DerivedCategory(); // GetType() != BaseCategory

// after — make them match
public Type ConfigType => typeof(DivedCategory);
public object Create() => new DerivedCategory();
Defensive patterns

Strategy: validation

Validate before calling

// For factory authors: keep ConfigType and Create() return type identical
Debug.Assert(typeof(MyCategory) == factory.ConfigType);

Type guard

static bool FactoryTypeConsistent(IConfigFactory f)
{
    object o = f.Create();
    return o != null && o.GetType() == f.ConfigType;
}

Prevention

When it happens

Trigger: GetConfigFactory resolved a factory whose ConfigType is X, but Create() returns an instance whose GetType() is Y != X. Happens when a factory's ConfigType and its Create() return type disagree (e.g. factory returns a base class or a sibling category).

Common situations: A factory's ConfigType was edited but Create() wasn't updated; a codegen template mismatch; a factory that returns a derived type where the exact-type check requires the declared category.

Related errors


AI-assisted analysis of egametang/ET@5cab01f7a8 (2026-08-13). Data as JSON: /api/errors/f6bd3525ba448851. Report an issue: GitHub.