eyaltoledano/claude-task-master · error
Invalid transition: ${event.type} from ${this.currentPhase}
Error message
Invalid transition: ${event.type} from ${this.currentPhase} What it means
The orchestrator validates each event against its transition table, matching (from=currentPhase, event=type). If no transition is registered for the current phase/event pair, transition() throws this error instead of silently ignoring the event — the state machine only allows explicitly declared moves.
Source
Thrown at packages/tm-core/src/modules/workflow/orchestrators/workflow-orchestrator.ts:139
this.handleRetry();
await this.triggerAutoPersist();
return;
}
// Handle TDD phase transitions within SUBTASK_LOOP
if (this.currentPhase === 'SUBTASK_LOOP') {
await this.handleTDDPhaseTransition(event);
await this.triggerAutoPersist();
return;
}
// Handle main workflow phase transitions
const validTransition = this.transitions.find(
(t) => t.from === this.currentPhase && t.event === event.type
);
if (!validTransition) {
throw new Error(
`Invalid transition: ${event.type} from ${this.currentPhase}`
);
}
// Execute transition
this.executeTransition(validTransition, event);
await this.triggerAutoPersist();
}
/**
* Handle TDD phase transitions (RED -> GREEN -> COMMIT)
*/
private async handleTDDPhaseTransition(event: WorkflowEvent): Promise<void> {
const currentTDD = this.context.currentTDDPhase || 'RED';
switch (event.type) {
case 'RED_PHASE_COMPLETE':
if (currentTDD !== 'RED') {View on GitHub (pinned to c0c98d367c)
Solutions
- Log this.currentPhase and the event type from the message to see exactly which move is illegal.
- Check the orchestrator's phase before dispatching (e.g. only send COMPLETE_PHASE when in an active phase).
- Deduplicate/serialize event dispatch — don't fire transition() concurrently from multiple code paths.
- If starting fresh, ensure startWorkflow is called only once per orchestrator instance.
- Verify the transitions table includes the intended edge if you extended the state machine.
Example fix
// before
await orchestrator.transition({ type: 'COMPLETE_PHASE' }); // maybe already done
// after
if (orchestrator.currentPhase !== 'COMPLETE') {
await orchestrator.transition({ type: 'COMPLETE_PHASE' });
} Defensive patterns
Strategy: validation
Validate before calling
const allowed = orchestrator.transitions
.filter((t) => t.from === orchestrator.currentPhase)
.map((t) => t.event);
if (!allowed.includes(event.type)) {
throw new SkipDispatchError(`${event.type} illegal from ${orchestrator.currentPhase}`);
} Type guard
function isLegalTransition(o, event) {
return o.transitions.some(
(t) => t.from === o.currentPhase && t.event === event.type
);
} Try / catch
try {
await orchestrator.transition(event);
} catch (e) {
if (e.message.startsWith('Invalid transition:')) {
console.warn(`skipped ${event.type}: ${e.message}`);
return; // or resync state
}
throw e;
} Prevention
- Track current phase in the caller and dispatch accordingly
- Serialize all transition() calls (avoid concurrent dispatch)
- Make startWorkflow idempotent at the call site
- Unit-test state machine paths for duplicated/out-of-order events
When it happens
Trigger: Dispatching an event that is not valid for the current phase, e.g. START_WORKFLOW when already initialized, COMPLETE_PHASE out of order, COMMIT in a non-committable phase, or duplicate events already consumed by a prior transition.
Common situations: Calling startWorkflow() twice; firing COMPLETE_PHASE twice for one phase; events racing so two callers transition the same orchestrator concurrently; replaying a persisted event log against an already-advanced state.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- Invalid transition: GREEN_PHASE_COMPLETE from non-GREEN phas
- Invalid transition: COMMIT_COMPLETE from non-COMMIT phase
- Workflow has been aborted
- Invalid transition: RED_PHASE_COMPLETE from non-RED phase
- Invalid transition: ${event.type} in SUBTASK_LOOP
AI-assisted analysis of eyaltoledano/claude-task-master@c0c98d367c (2026-08-29).
Data as JSON: /api/errors/02f874938c233961.
Report an issue: GitHub.