alibaba/COLA · error · StateMachineException

There is no stateMachine instance for ${machineId}, please b

Error message

There is no stateMachine instance for ${machineId}, please build it first

What it means

StateMachineFactory.get() looks up a built state machine by machineId in the static registry and throws this StateMachineException when no machine with that id has been built/registered. It is a lookup failure: the caller referenced a machine id that was never built in this JVM.

Source

Thrown at cola-components/cola-component-statemachine/src/main/java/com/alibaba/cola/statemachine/StateMachineFactory.java:28

 *
 * @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)

Solutions

  1. Build the machine first via StateMachineBuilder before calling get(), with the exact same machineId
  2. Verify the machineId string matches the one used at build time (extract it to a constant)
  3. Check initialization ordering / ensure the builder bean is initialized before consumers call get()

Example fix

// before
StateMachine<...> sm = StateMachineFactory.get("orderSM"); // never built -> throws

// after
StateMachine<...> sm = StateMachineFactory.get(STATE_MACHINE_ID);
if (sm == null) {
    sm = buildOrderStateMachine(STATE_MACHINE_ID);
}
Defensive patterns

Strategy: validation

Validate before calling

StateMachine sm = StateMachineFactory.get(machineId);
if (sm == null) {
    throw new IllegalStateException("Build state machine first: " + machineId);
}

Try / catch

try {
    sm = StateMachineFactory.get(machineId);
} catch (StateMachineException e) {
    if (e.getMessage().contains("please build it first")) {
        sm = buildStateMachine(machineId); // build then retry
    } else {
        throw e;
    }
}

Prevention

When it happens

Trigger: Calling StateMachineFactory.get("someId") before building the machine, with a typo in the machineId, or after the building code never ran (e.g. missing configuration/bean initialization).

Common situations: Typos or renamed machine ids; consumer code running in a different JVM/module than the builder; startup ordering where get() runs before build().

Understand the failure class

Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.

Related errors


AI-assisted analysis of alibaba/COLA@352e1a8675 (2026-09-08). Data as JSON: /api/errors/9ef1083a2ab6c0a1. Report an issue: GitHub.