{"record":{"id":"70f1999b0ee03701","repo":"EllanJiang/GameFramework","slug":"state-type-is-invalid-fsmstate","errorCode":null,"errorMessage":"State type is invalid.","messagePattern":"State type is invalid\\.","errorType":"exception","errorClass":"GameFrameworkException","httpStatus":null,"severity":"error","filePath":"GameFramework/Fsm/FsmState.cs","lineNumber":99,"sourceCode":"            fsmImplement.ChangeState<TState>();\n        }\n\n        /// <summary>\n        /// 切换当前有限状态机状态。\n        /// </summary>\n        /// <param name=\"fsm\">有限状态机引用。</param>\n        /// <param name=\"stateType\">要切换到的有限状态机状态类型。</param>\n        protected void ChangeState(IFsm<T> fsm, Type stateType)\n        {\n            Fsm<T> fsmImplement = (Fsm<T>)fsm;\n            if (fsmImplement == null)\n            {\n                throw new GameFrameworkException(\"FSM is invalid.\");\n            }\n\n            if (stateType == null)\n            {\n                throw new GameFrameworkException(\"State type is invalid.\");\n            }\n\n            if (!typeof(FsmState<T>).IsAssignableFrom(stateType))\n            {\n                throw new GameFrameworkException(Utility.Text.Format(\"State type '{0}' is invalid.\", stateType.FullName));\n            }\n\n            fsmImplement.ChangeState(stateType);\n        }\n    }\n}\n","sourceCodeStart":81,"sourceCodeEnd":111,"githubUrl":"https://github.com/EllanJiang/GameFramework/blob/d0c010b05167c58e92350449d04864a91ca13fd2/GameFramework/Fsm/FsmState.cs#L81-L111","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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)"],"exampleFix":"// before\nType stateType = Type.GetType(config.NextState); // may be null or wrong base\nstate.ChangeState(fsm, stateType);\n// after\nType stateType = Type.GetType(config.NextState);\nif (stateType != null && typeof(FsmState<Player>).IsAssignableFrom(stateType))\n{\n    state.ChangeState(fsm, stateType);\n}","handlingStrategy":"validation","validationCode":"if (stateType != null && typeof(FsmState<T>).IsAssignableFrom(stateType))\n    ChangeState(fsm, stateType);","typeGuard":"static bool IsValidStateType<T>(Type t) where T : class => t != null && typeof(FsmState<T>).IsAssignableFrom(t);","tryCatchPattern":"try { ChangeState(fsm, stateType); }\ncatch (GameFrameworkException ex) { Log.Error(\"Invalid state type '{0}': {1}\", stateType?.FullName, ex.Message); }","preventionTips":["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"],"tags":["csharp","fsm","state-machine","null-argument","type-mismatch"],"backgroundTag":"invalid-state-transition","analyzedSha":"d0c010b05167c58e92350449d04864a91ca13fd2","analyzedAt":"2026-09-15T13:37:15.352Z","contentChangedAt":"2026-09-15T13:37:15.352Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}