eyaltoledano/claude-task-master · error

Test results required for RED phase transition

Error message

Test results required for RED phase transition

What it means

A RED_PHASE_COMPLETE event signals the end of the RED (write failing tests) phase, so the orchestrator requires the event to carry testResults proving the tests ran. Dispatching RED_PHASE_COMPLETE without testResults throws this error — the transition cannot proceed without evidence.

Source

Thrown at packages/tm-core/src/modules/workflow/orchestrators/workflow-orchestrator.ts:165

	}

	/**
	 * 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') {
					throw new Error(
						'Invalid transition: RED_PHASE_COMPLETE from non-RED phase'
					);
				}

				// Validate test results are provided
				if (!event.testResults) {
					throw new Error('Test results required for RED phase transition');
				}

				// Store test results in context
				this.context.lastTestResults = event.testResults;

				// Special case: All tests passing in RED phase means feature already implemented
				if (event.testResults.failed === 0) {
					this.emit('tdd:red:completed');
					this.emit('tdd:feature-already-implemented', {
						subtaskId: this.getCurrentSubtaskId(),
						testResults: event.testResults
					});

					// Mark subtask as complete and move to next one
					const subtask =
						this.context.subtasks[this.context.currentSubtaskIndex];
					if (subtask) {
						subtask.status = 'completed';

View on GitHub (pinned to c0c98d367c)

Solutions

  1. Always attach testResults to the RED_PHASE_COMPLETE event: { type: 'RED_PHASE_COMPLETE', testResults: results }.
  2. Ensure the test suite actually runs and returns a results object before signaling completion.
  3. If the runner failed, dispatch the ERROR event instead of faking a RED completion.
  4. Add a pre-dispatch check: if (!event.testResults) run the suite first.

Example fix

// before
await orchestrator.transition({ type: 'RED_PHASE_COMPLETE' });
// after
const results = await runTests();
await orchestrator.transition({ type: 'RED_PHASE_COMPLETE', testResults: results });
Defensive patterns

Strategy: validation

Validate before calling

function assertTestResults(event) {
  if (event.type === 'RED_PHASE_COMPLETE' && !event.testResults) {
    throw new TypeError('RED_PHASE_COMPLETE requires testResults');
  }
}
assertTestResults(event);
await orchestrator.transition(event);

Type guard

function hasTestResults(e) {
  return e.type !== 'RED_PHASE_COMPLETE'
    || (typeof e.testResults === 'object' && e.testResults !== null);
}

Try / catch

try {
  await orchestrator.transition(event);
} catch (e) {
  if (e.message === 'Test results required for RED phase transition') {
    const results = await runTests();
    await orchestrator.transition({ ...event, testResults: results });
  } else throw e;
}

Prevention

When it happens

Trigger: transition({ type: 'RED_PHASE_COMPLETE' }) with testResults undefined or omitted while currentTDDPhase is RED, e.g. signaling phase completion before the test suite has executed.

Common situations: Hooking phase advancement to file-save instead of test-run completion; a test runner that crashed and produced no results object; calling the transition manually in scripts without constructing the full event payload.

Related errors


AI-assisted analysis of eyaltoledano/claude-task-master@c0c98d367c (2026-08-29). Data as JSON: /api/errors/47708c04c8af4ace. Report an issue: GitHub.