EllanJiang/GameFramework · error · GameFrameworkException
State type is invalid.
Error message
State type is invalid.
What it means
In FsmState<T>.ChangeState(IFsm<T> fsm, Type stateType), after validating the FSM the library checks that stateType is non-null and assignable to FsmState<T>. It throws GameFrameworkException("State type is invalid.") when stateType is null, and a formatted variant when the type is not a valid state of this FSM.
Solutions
- Pass typeof(ConcreteStateClass) directly instead of reflection-resolved types
- If the Type comes from a string, null-check Type.GetType output before calling
- Ensure the target type derives from FsmState<T> for the same owner type T
- Prevent code stripping of state classes under IL2CPP (preserve attribute / link.xml)
Example fix
// before
Type stateType = Type.GetType(config.NextState); // may be null or wrong base
state.ChangeState(fsm, stateType);
// after
Type stateType = Type.GetType(config.NextState);
if (stateType != null && typeof(FsmState<Player>).IsAssignableFrom(stateType))
{
state.ChangeState(fsm, stateType);
} Defensive patterns
Strategy: validation
Validate before calling
if (stateType != null && typeof(FsmState<T>).IsAssignableFrom(stateType))
ChangeState(fsm, stateType); Type guard
static bool IsValidStateType<T>(Type t) where T : class => t != null && typeof(FsmState<T>).IsAssignableFrom(t);
Try / catch
try { ChangeState(fsm, stateType); }
catch (GameFrameworkException ex) { Log.Error("Invalid state type '{0}': {1}", stateType?.FullName, ex.Message); } Prevention
- Prefer typeof() literals over string-resolved types
- Null- and base-type-check Type.GetType results
- Preserve state classes from IL2CPP stripping in AOT builds
- Ensure state types match the FSM's owner type T
When it happens
Trigger: Calling ChangeState(fsm, null); or passing a Type that does not derive from Fsm<T>'s state base (raises the related "State type '{0}' is invalid." message).
Common situations: Resolving state Type from string configs where the name is misspelled or the class was renamed/refactored (Type.GetType returns null); passing a state class belonging to a different FSM's owner type; stripped types in IL2CPP/AOT builds.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
AI-assisted analysis of EllanJiang/GameFramework@d0c010b051 (2026-09-15).
Data as JSON: /api/errors/70f1999b0ee03701.
Report an issue: GitHub.
Appendix: source
Thrown at GameFramework/Fsm/FsmState.cs:99
fsmImplement.ChangeState<TState>();
}
/// <summary>
/// 切换当前有限状态机状态。
/// </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)