EllanJiang/GameFramework · error · GameFrameworkException
FSM ' ' state ' ' is already exist.
Error message
FSM '{0}' state '{1}' is already exist. What it means
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.
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.
Example fix
// before
var fsm = Fsm<Enemy>.Create("Enemy", this, new IdleState(), new IdleState());
// after
var fsm = Fsm<Enemy>.Create("Enemy", this, new IdleState()); Defensive patterns
Strategy: validation
Validate before calling
var seen = new HashSet<Type>();
foreach (var s in states)
{
if (!seen.Add(s.GetType()))
throw new InvalidOperationException($"Duplicate state type {s.GetType().Name}.");
}
var fsm = Fsm<Enemy>.Create("Enemy", this, states); Type guard
bool HasNoDuplicateStates<T>(IEnumerable<FsmState<T>> states) where T : class => states.Select(s => s.GetType()).Distinct().Count() == states.Count();
Try / catch
try { fsm = Fsm<Enemy>.Create("Enemy", this, states); }
catch (GameFrameworkException ex) { Log.Error("Duplicate FSM state: " + ex.Message); } Prevention
- 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.
When it happens
Trigger: Fsm<T>.Create(name, owner, new StateA(), new StateA()) — any duplicated concrete FsmState<T> subclass in the params array or List overload input.
Common situations: 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.
Understand the failure class
Background: "already exists" / EEXIST / FileAlreadyExistsException: what the 'file already exists' error means and how to fix it — this error's family across 37 libraries.
Related errors
- Already exist FSM ' '.
- Already exist ' ' in data table ' '.
- FSM owner is invalid.
- FSM states is invalid.
- FSM is running, can not start again.
AI-assisted analysis of EllanJiang/GameFramework@d0c010b051 (2026-09-15).
Data as JSON: /api/errors/5d8e9accef6b50e4.
Report an issue: GitHub.
Appendix: source
Thrown at GameFramework/Fsm/Fsm.cs:160
{
throw new GameFrameworkException("FSM states is invalid.");
}
Fsm<T> fsm = ReferencePool.Acquire<Fsm<T>>();
fsm.Name = name;
fsm.m_Owner = owner;
fsm.m_IsDestroyed = false;
foreach (FsmState<T> state in states)
{
if (state == null)
{
throw new GameFrameworkException("FSM states is invalid.");
}
Type stateType = state.GetType();
if (fsm.m_States.ContainsKey(stateType))
{
throw new GameFrameworkException(Utility.Text.Format("FSM '{0}' state '{1}' is already exist.", new TypeNamePair(typeof(T), name), stateType.FullName));
}
fsm.m_States.Add(stateType, state);
state.OnInit(fsm);
}
return fsm;
}
/// <summary>
/// 创建有限状态机。
/// </summary>
/// <param name="name">有限状态机名称。</param>
/// <param name="owner">有限状态机持有者。</param>
/// <param name="states">有限状态机状态集合。</param>
/// <returns>创建的有限状态机。</returns>
public static Fsm<T> Create(string name, T owner, List<FsmState<T>> states)
{View on GitHub (pinned to d0c010b051)