{"record":{"id":"5d8e9accef6b50e4","repo":"EllanJiang/GameFramework","slug":"fsm-0-state-1-is-already-exist","errorCode":null,"errorMessage":"FSM '{0}' state '{1}' is already exist.","messagePattern":"FSM '(.+?)' state '(.+?)' is already exist\\.","errorType":"exception","errorClass":"GameFrameworkException","httpStatus":null,"severity":"error","filePath":"GameFramework/Fsm/Fsm.cs","lineNumber":160,"sourceCode":"            {\n                throw new GameFrameworkException(\"FSM states is invalid.\");\n            }\n\n            Fsm<T> fsm = ReferencePool.Acquire<Fsm<T>>();\n            fsm.Name = name;\n            fsm.m_Owner = owner;\n            fsm.m_IsDestroyed = false;\n            foreach (FsmState<T> state in states)\n            {\n                if (state == null)\n                {\n                    throw new GameFrameworkException(\"FSM states is invalid.\");\n                }\n\n                Type stateType = state.GetType();\n                if (fsm.m_States.ContainsKey(stateType))\n                {\n                    throw new GameFrameworkException(Utility.Text.Format(\"FSM '{0}' state '{1}' is already exist.\", new TypeNamePair(typeof(T), name), stateType.FullName));\n                }\n\n                fsm.m_States.Add(stateType, state);\n                state.OnInit(fsm);\n            }\n\n            return fsm;\n        }\n\n        /// <summary>\n        /// 创建有限状态机。\n        /// </summary>\n        /// <param name=\"name\">有限状态机名称。</param>\n        /// <param name=\"owner\">有限状态机持有者。</param>\n        /// <param name=\"states\">有限状态机状态集合。</param>\n        /// <returns>创建的有限状态机。</returns>\n        public static Fsm<T> Create(string name, T owner, List<FsmState<T>> states)\n        {","sourceCodeStart":142,"sourceCodeEnd":178,"githubUrl":"https://github.com/EllanJiang/GameFramework/blob/d0c010b05167c58e92350449d04864a91ca13fd2/GameFramework/Fsm/Fsm.cs#L142-L178","documentation":"Fsm<T>.Create registers each state in a dictionary keyed by the state's concrete Type. Passing two instances of the same state type fails the ContainsKey check at Fsm.cs:160 and throws this formatted exception naming the FSM and the duplicate type.","triggerScenarios":"Fsm<T>.Create(name, owner, new StateA(), new StateA()) — any duplicated concrete FsmState<T> subclass in the params array or List overload input.","commonSituations":"Programmatically generating the state list (e.g. one instance per enum flag) where a flag maps to the same state class twice; copy-paste duplicating a state in the Create call; merging two state lists without de-duplicating.","solutions":["Remove the duplicate state instance so each concrete FsmState<T> subclass appears exactly once.","De-duplicate by type before Create: states = states.DistinctBy(s => s.GetType()).ToList() (or a loop with a HashSet<Type>).","If you need the same behavior in two states, extract shared logic into a common base class and create two distinct subclasses."],"exampleFix":"// before\nvar fsm = Fsm<Enemy>.Create(\"Enemy\", this, new IdleState(), new IdleState());\n// after\nvar fsm = Fsm<Enemy>.Create(\"Enemy\", this, new IdleState());","handlingStrategy":"validation","validationCode":"var seen = new HashSet<Type>();\nforeach (var s in states)\n{\n    if (!seen.Add(s.GetType()))\n        throw new InvalidOperationException($\"Duplicate state type {s.GetType().Name}.\");\n}\nvar fsm = Fsm<Enemy>.Create(\"Enemy\", this, states);","typeGuard":"bool HasNoDuplicateStates<T>(IEnumerable<FsmState<T>> states) where T : class => states.Select(s => s.GetType()).Distinct().Count() == states.Count();","tryCatchPattern":"try { fsm = Fsm<Enemy>.Create(\"Enemy\", this, states); }\ncatch (GameFrameworkException ex) { Log.Error(\"Duplicate FSM state: \" + ex.Message); }","preventionTips":["Keep a single source of truth for the state list; avoid merging lists without de-duplication.","If two states need identical behavior, factor shared logic into a base class with distinct subclasses."],"tags":["csharp","fsm","duplicate-key"],"backgroundTag":"file-already-exists","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"}