alibaba/COLA · error · StateMachineException
The state machine with id
Error message
The state machine with id [${machineId}] is already built, no need to build again What it means
StateMachineFactory keeps a static registry of state machines keyed by machineId. register() throws this StateMachineException when a machine with the same id is already present in the map, to enforce one machine per id. It fires when the same machineId is built and registered twice.
Solutions
- Use StateMachineFactory.get(machineId) first and only build/register when it returns null
- Use unique machineIds (e.g. append a timestamp/UUID) if multiple instances are intentional
- Guard initialization with a singleton/once flag so build code runs once per JVM
- In tests, build in a static initializer or check the factory cache before rebuilding
Example fix
// before
StateMachine<...> sm = builder.build("orderSM"); // second call throws
// after
StateMachine<...> sm = StateMachineFactory.get("orderSM");
if (sm == null) {
sm = builder.build("orderSM");
} Defensive patterns
Strategy: validation
Validate before calling
if (StateMachineFactory.get(machineId) != null) {
throw new IllegalStateException("machineId already registered: " + machineId);
} Try / catch
try {
StateMachineFactory.register(sm);
} catch (StateMachineException e) {
if (e.getMessage().contains("already built")) {
sm = StateMachineFactory.get(machineId); // reuse existing
} else {
throw e;
}
} Prevention
- Check StateMachineFactory.get(machineId) before building
- Use a constant or UUID-based machineId scheme
- Initialize state machines once (singleton/static init)
- In tests, reuse the factory cache across test methods
When it happens
Trigger: Calling StateMachineBuilder.builder(...) ... build(machineId) (or StateMachineFactory.register) twice with the same machineId, e.g. re-running initialization code on app restart within the same JVM or duplicate Spring bean creation.
Common situations: Hot-reload or repeated initialization of state machines in tests (multiple @BeforeAll building the same id); duplicate bean definitions; classloader re-loading in app servers.
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
- There is no stateMachine instance for
- already Exist, you can not add another one
- Cannot fire event [ ] on current state [ ] with context [ ]
- is not found, please check state machine
- EXTENSION_DEFINE_DUPLICATE
AI-assisted analysis of alibaba/COLA@352e1a8675 (2026-09-08).
Data as JSON: /api/errors/8a17f0863062bc9e.
Report an issue: GitHub.
Appendix: source
Thrown at cola-components/cola-component-statemachine/src/main/java/com/alibaba/cola/statemachine/StateMachineFactory.java:20
import com.alibaba.cola.statemachine.impl.StateMachineException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* StateMachineFactory
*
* @author Frank Zhang
* @date 2020-02-08 10:21 PM
*/
public class StateMachineFactory {
static Map<String /* machineId */, StateMachine> stateMachineMap = new ConcurrentHashMap<>();
public static <S, E, C> void register(StateMachine<S, E, C> stateMachine){
String machineId = stateMachine.getMachineId();
if(stateMachineMap.get(machineId) != null){
throw new StateMachineException("The state machine with id ["+machineId+"] is already built, no need to build again");
}
stateMachineMap.put(stateMachine.getMachineId(), stateMachine);
}
public static <S, E, C> StateMachine<S, E, C> get(String machineId){
StateMachine stateMachine = stateMachineMap.get(machineId);
if(stateMachine == null){
throw new StateMachineException("There is no stateMachine instance for "+machineId+", please build it first");
}
return stateMachine;
}
}
View on GitHub (pinned to 352e1a8675)