EllanJiang/GameFramework · error · GameFrameworkException

State type ' ' is invalid.

Error message

State type '{0}' is invalid.

What it means

Thrown by the FSM extension's ChangeState when the requested state type is not a valid FSM state. It fires in two cases covered by the surrounding checks: the state type is null ("State type is invalid") or it does not derive from FsmState<T> for the FSM's owner type T. GameFramework requires every state in an Fsm<T> to inherit from FsmState<T> so lifecycle methods (OnInit, OnEnter, OnUpdate, OnLeave) can be invoked safely.

Solutions

  1. Make the state class inherit from FsmState<T> using exactly the same owner type T as the FSM, e.g. public class MyState : FsmState<MyOwner>.
  2. Verify the argument passed to ChangeState is typeof(MyState) of the correct state class, not null or a base/interface type.
  3. If resolving types from strings/assemblies, check the resolved type with typeof(FsmState<T>).IsAssignableFrom(resolvedType) before calling ChangeState.

Example fix

// before
fsm.ChangeState(typeof(PlayerState)); // PlayerState : FsmState<Enemy> (wrong owner)

// after
public class PlayerState : FsmState<Player> { }
fsm.ChangeState(typeof(PlayerState)); // matches Fsm<Player> owner type
Defensive patterns

Strategy: validation

Validate before calling

if (stateType == null || !typeof(FsmState<T>).IsAssignableFrom(stateType))
    throw new ArgumentException($"{stateType} is not a valid FsmState<T> for this FSM");

Type guard

static bool IsValidFsmState<T>(Type t) => t != null && typeof(FsmState<T>).IsAssignableFrom(t);

Try / catch

try { fsm.ChangeState(typeof(MyState)); }
catch (GameFrameworkException ex) { Log.Error("Invalid state type: " + ex.Message); }

Prevention

When it happens

Trigger: Calling FsmExtension.ChangeState<T>(fsm, stateType) or ChangeState(fsm, stateType, userData) where stateType is null, where stateType is a non-FsmState class (e.g. a plain class or interface type), or where the state derives from FsmState<OtherOwner> while the FSM is Fsm<T> with a different owner type.

Common situations: Typo or refactoring passing the wrong Type object; passing typeof(SomeBaseClass) that only implements a similar interface; copy-pasting states across FSMs with different owner types so the generic parameter no longer matches; loading state types dynamically by name and getting an unrelated type.

Understand the failure class

Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.

Related errors


AI-assisted analysis of EllanJiang/GameFramework@d0c010b051 (2026-09-15). Data as JSON: /api/errors/462b9b0ef2f492f2. Report an issue: GitHub.

Appendix: source

Thrown at GameFramework/Fsm/FsmState.cs:104

        /// </summary>
        /// <param name="fsm">有限状态机引用。</param>
        /// <param name="stateType">要切换到的有限状态机状态类型。</param>
        protected void ChangeState(IFsm<T> fsm, Type stateType)
        {
            Fsm<T> fsmImplement = (Fsm<T>)fsm;
            if (fsmImplement == null)
            {
                throw new GameFrameworkException("FSM is invalid.");
            }

            if (stateType == null)
            {
                throw new GameFrameworkException("State type is invalid.");
            }

            if (!typeof(FsmState<T>).IsAssignableFrom(stateType))
            {
                throw new GameFrameworkException(Utility.Text.Format("State type '{0}' is invalid.", stateType.FullName));
            }

            fsmImplement.ChangeState(stateType);
        }
    }
}

View on GitHub (pinned to d0c010b051)