{"record":{"id":"fdd69b4e83202521","repo":"eyaltoledano/claude-task-master","slug":"invalid-transition-red-phase-complete-from-non-re","errorCode":null,"errorMessage":"Invalid transition: RED_PHASE_COMPLETE from non-RED phase","messagePattern":"Invalid transition: RED_PHASE_COMPLETE from non-RED phase","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/tm-core/src/modules/workflow/orchestrators/workflow-orchestrator.ts","lineNumber":158,"sourceCode":"\t\t\t\t`Invalid transition: ${event.type} from ${this.currentPhase}`\n\t\t\t);\n\t\t}\n\n\t\t// Execute transition\n\t\tthis.executeTransition(validTransition, event);\n\t\tawait this.triggerAutoPersist();\n\t}\n\n\t/**\n\t * Handle TDD phase transitions (RED -> GREEN -> COMMIT)\n\t */\n\tprivate async handleTDDPhaseTransition(event: WorkflowEvent): Promise<void> {\n\t\tconst currentTDD = this.context.currentTDDPhase || 'RED';\n\n\t\tswitch (event.type) {\n\t\t\tcase 'RED_PHASE_COMPLETE':\n\t\t\t\tif (currentTDD !== 'RED') {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t'Invalid transition: RED_PHASE_COMPLETE from non-RED phase'\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\t// Validate test results are provided\n\t\t\t\tif (!event.testResults) {\n\t\t\t\t\tthrow new Error('Test results required for RED phase transition');\n\t\t\t\t}\n\n\t\t\t\t// Store test results in context\n\t\t\t\tthis.context.lastTestResults = event.testResults;\n\n\t\t\t\t// Special case: All tests passing in RED phase means feature already implemented\n\t\t\t\tif (event.testResults.failed === 0) {\n\t\t\t\t\tthis.emit('tdd:red:completed');\n\t\t\t\t\tthis.emit('tdd:feature-already-implemented', {\n\t\t\t\t\t\tsubtaskId: this.getCurrentSubtaskId(),\n\t\t\t\t\t\ttestResults: event.testResults","sourceCodeStart":140,"sourceCodeEnd":176,"githubUrl":"https://github.com/eyaltoledano/claude-task-master/blob/c0c98d367c55296bfe69e65680625b6db437af02/packages/tm-core/src/modules/workflow/orchestrators/workflow-orchestrator.ts#L140-L176","documentation":"TDD sub-phase events are handled by handleTDDPhaseTransition(). RED_PHASE_COMPLETE is only legal when the workflow's currentTDDPhase is 'RED'; dispatching it from GREEN or REFACTOR throws this fixed-message error, since a RED-phase completion implies test results concluding the RED phase.","triggerScenarios":"Dispatching { type: 'RED_PHASE_COMPLETE' } when context.currentTDDPhase is 'GREEN' or 'REFACTOR' — e.g. double-completing the RED phase, or resuming an orchestrator whose TDD sub-state was already advanced.","commonSituations":"A test runner callback fires RED_PHASE_COMPLETE twice; restoring state where the RED→GREEN transition already happened; parallel agents each reporting RED completion for the same workflow.","solutions":["Check context.currentTDDPhase before dispatching; only send RED_PHASE_COMPLETE from RED.","If the RED phase already completed, send the next appropriate event (e.g. GREEN/REFACTOR phase events) instead.","Deduplicate test-runner callbacks so completion fires once.","When resuming from persisted state, confirm currentTDDPhase was persisted correctly before replaying events."],"exampleFix":"// before\nawait orchestrator.transition({ type: 'RED_PHASE_COMPLETE', testResults });\n// after\nif ((orchestrator.context.currentTDDPhase ?? 'RED') === 'RED') {\n  await orchestrator.transition({ type: 'RED_PHASE_COMPLETE', testResults });\n}","handlingStrategy":"validation","validationCode":"const tdd = orchestrator.context.currentTDDPhase || 'RED';\nif (event.type === 'RED_PHASE_COMPLETE' && tdd !== 'RED') {\n  throw new SkipDispatchError('RED_PHASE_COMPLETE illegal outside RED phase');\n}","typeGuard":"function canCompleteRed(ctx, event) {\n  return event.type !== 'RED_PHASE_COMPLETE'\n    || (ctx.currentTDDPhase || 'RED') === 'RED';\n}","tryCatchPattern":"try {\n  await orchestrator.transition(event);\n} catch (e) {\n  if (e.message.includes('RED_PHASE_COMPLETE from non-RED phase')) {\n    console.warn('RED already completed; dispatch next phase event instead');\n    return;\n  }\n  throw e;\n}","preventionTips":["Persist currentTDDPhase with workflow state so resumes know the sub-phase","Fire RED_PHASE_COMPLETE exactly once per RED cycle (dedupe test-runner callbacks)","Route later-phase events to their own event types, not RED_PHASE_COMPLETE","Check currentTDDPhase before dispatching TDD events"],"tags":["tdd","state-machine","workflow"],"backgroundTag":"invalid-state-transition","analyzedSha":"c0c98d367c55296bfe69e65680625b6db437af02","analyzedAt":"2026-08-29T02:56:26.071Z","schemaVersion":2},"datasetVersion":"2026-08-29T07:17:48.351Z"}