{"record":{"id":"3cbdda56ffbc3b26","repo":"eyaltoledano/claude-task-master","slug":"invalid-transition-event-type-in-subtask-loop","errorCode":null,"errorMessage":"Invalid transition: ${event.type} in SUBTASK_LOOP","messagePattern":"Invalid transition: (.+?) in SUBTASK_LOOP","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/tm-core/src/modules/workflow/orchestrators/workflow-orchestrator.ts","lineNumber":289,"sourceCode":"\t\t\t\t\tthis.emit('tdd:red:started');\n\t\t\t\t\tthis.emit('subtask:started');\n\t\t\t\t} else {\n\t\t\t\t\t// All subtasks complete, transition to FINALIZE\n\t\t\t\t\tawait this.transition({ type: 'ALL_SUBTASKS_COMPLETE' });\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase 'ALL_SUBTASKS_COMPLETE':\n\t\t\t\t// Transition to FINALIZE phase\n\t\t\t\tthis.emit('phase:exited');\n\t\t\t\tthis.currentPhase = 'FINALIZE';\n\t\t\t\tthis.context.currentTDDPhase = undefined;\n\t\t\t\tthis.emit('phase:entered');\n\t\t\t\t// Note: Don't auto-transition to COMPLETE - requires explicit finalize call\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tthrow new Error(`Invalid transition: ${event.type} in SUBTASK_LOOP`);\n\t\t}\n\t}\n\n\t/**\n\t * Execute a state transition\n\t */\n\tprivate executeTransition(\n\t\ttransition: StateTransition,\n\t\tevent: WorkflowEvent\n\t): void {\n\t\t// Check guard condition if present\n\t\tif (transition.guard && !transition.guard(this.context)) {\n\t\t\tthrow new Error(\n\t\t\t\t`Guard condition failed for transition to ${transition.to}`\n\t\t\t);\n\t\t}\n\n\t\t// Check phase-specific guard if present","sourceCodeStart":271,"sourceCodeEnd":307,"githubUrl":"https://github.com/eyaltoledano/claude-task-master/blob/c0c98d367c55296bfe69e65680625b6db437af02/packages/tm-core/src/modules/workflow/orchestrators/workflow-orchestrator.ts#L271-L307","documentation":"While the workflow is in the SUBTASK_LOOP phase, handleTDDPhaseTransition only accepts a fixed set of events: RED_PHASE_COMPLETE, GREEN_PHASE_COMPLETE, COMMIT_COMPLETE, SUBTASK_COMPLETE, and ALL_SUBTASKS_COMPLETE. This default branch throws for any other event.type, protecting the state machine from unknown or phase-mismatched events (e.g. workflow-level events meant for other phases such as start/finalize events).","triggerScenarios":"Calling transition({ type: '<anything else>' }) while currentPhase is SUBTASK_LOOP — e.g. START, FINALIZE_COMPLETE, PAUSE, a typo like 'SUBTASK_COMPLETED', or an event belonging to the PLANNING/FINALIZE phases.","commonSituations":"Typo in the event type string; sending workflow-level control events during the subtask loop; copy-pasted dispatch code from a different phase; a version change renaming or removing an event type so older callers send obsolete names.","solutions":["Use one of the valid SUBTASK_LOOP events: RED_PHASE_COMPLETE, GREEN_PHASE_COMPLETE, COMMIT_COMPLETE, SUBTASK_COMPLETE, or ALL_SUBTASKS_COMPLETE.","Check the event type string for typos and exact casing against the WorkflowEvent type definition.","If you need to finalize or move to another workflow phase, use the orchestrator's dedicated API (e.g. the explicit finalize call) instead of transitioning events while in SUBTASK_LOOP.","Update callers if the event was renamed in a newer version of @tm/core."],"exampleFix":"// before\nawait orchestrator.transition({ type: 'SUBTASK_COMPLETED' }); // typo\n\n// after\nawait orchestrator.transition({ type: 'SUBTASK_COMPLETE' });","handlingStrategy":"validation","validationCode":"const SUBTASK_LOOP_EVENTS = ['RED_PHASE_COMPLETE', 'GREEN_PHASE_COMPLETE', 'COMMIT_COMPLETE', 'SUBTASK_COMPLETE', 'ALL_SUBTASKS_COMPLETE'] as const;\nif (!SUBTASK_LOOP_EVENTS.includes(event.type as never)) {\n  throw new Error(`Event ${event.type} not allowed while in SUBTASK_LOOP`);\n}","typeGuard":"type SubtaskLoopEvent = 'RED_PHASE_COMPLETE' | 'GREEN_PHASE_COMPLETE' | 'COMMIT_COMPLETE' | 'SUBTASK_COMPLETE' | 'ALL_SUBTASKS_COMPLETE';\nfunction isSubtaskLoopEvent(t: string): t is SubtaskLoopEvent {\n  return (['RED_PHASE_COMPLETE', 'GREEN_PHASE_COMPLETE', 'COMMIT_COMPLETE', 'SUBTASK_COMPLETE', 'ALL_SUBTASKS_COMPLETE'] as const).includes(t as SubtaskLoopEvent);\n}","tryCatchPattern":"try {\n  await orchestrator.transition(event);\n} catch (e) {\n  if (e instanceof Error && e.message.includes('in SUBTASK_LOOP')) {\n    // event.type is not valid here — map it to a valid SUBTASK_LOOP event or use the phase-specific API\n  } else {\n    throw e;\n  }\n}","preventionTips":["Use TypeScript discriminated unions for WorkflowEvent so invalid event types fail at compile time.","Keep a central constant/list of valid events per workflow phase and validate against it before dispatching.","Check event type spelling/casing when upgrading @tm-core versions in case event names changed."],"tags":["state-machine","workflow","unknown-event","invalid-input"],"backgroundTag":"invalid-state-transition","analyzedSha":"c0c98d367c55296bfe69e65680625b6db437af02","analyzedAt":"2026-08-29T02:56:26.071Z","schemaVersion":2},"datasetVersion":"2026-08-29T07:17:48.351Z"}