eyaltoledano/claude-task-master · error

Test results required for GREEN phase transition

Error message

Test results required for GREEN phase transition

What it means

When completing the GREEN (implementation) phase of the TDD cycle, the orchestrator requires the event to carry test results proving the implementation works. This error is thrown by handleTDDPhaseTransition when a GREEN_PHASE_COMPLETE event is dispatched with event.testResults undefined. The results are stored in context.lastTestResults and are validated to have zero failures before the workflow may advance to COMMIT.

Source

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

					break;
				}

				// Normal RED phase: has failing tests, proceed to GREEN
				this.emit('tdd:red:completed');
				this.context.currentTDDPhase = 'GREEN';
				this.emit('tdd:green:started');
				break;

			case 'GREEN_PHASE_COMPLETE':
				if (currentTDD !== 'GREEN') {
					throw new Error(
						'Invalid transition: GREEN_PHASE_COMPLETE from non-GREEN phase'
					);
				}

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

				// Validate GREEN phase has no failures
				if (event.testResults.failed !== 0) {
					throw new Error('GREEN phase must have zero failures');
				}

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

				this.emit('tdd:green:completed');
				this.context.currentTDDPhase = 'COMMIT';
				this.emit('tdd:commit:started');
				break;

			case 'COMMIT_COMPLETE':
				if (currentTDD !== 'COMMIT') {
					throw new Error(

View on GitHub (pinned to c0c98d367c)

Solutions

  1. Attach a test results summary to the event: transition({ type: 'GREEN_PHASE_COMPLETE', testResults: { total, passed, failed } }).
  2. Run the test suite and capture its summary before dispatching the GREEN_PHASE_COMPLETE event.
  3. If the test runner crashed and produced no summary, treat it as a failed GREEN phase rather than completing it; fix the runner or tests first.
  4. Guard the call site: only dispatch when a non-null testResults object exists.

Example fix

// before
await orchestrator.transition({ type: 'GREEN_PHASE_COMPLETE' });

// after
const testResults = await runTests(); // { total, passed, failed }
await orchestrator.transition({ type: 'GREEN_PHASE_COMPLETE', testResults });
Defensive patterns

Strategy: validation

Validate before calling

function hasTestResults(e: { type: string; testResults?: { total: number; passed: number; failed: number } }): boolean {
  return e.type === 'GREEN_PHASE_COMPLETE' && !!e.testResults && typeof e.testResults.failed === 'number';
}
// call: if (!hasTestResults(event)) throw new Error('Attach test results before GREEN_PHASE_COMPLETE');

Type guard

function hasTestResults(e: unknown): e is { type: 'GREEN_PHASE_COMPLETE'; testResults: { total: number; passed: number; failed: number } } {
  const ev = e as { type?: string; testResults?: { failed?: unknown } };
  return ev.type === 'GREEN_PHASE_COMPLETE' && !!ev.testResults && typeof ev.testResults.failed === 'number';
}

Try / catch

try {
  await orchestrator.transition(event);
} catch (e) {
  if (e instanceof Error && e.message.includes('Test results required for GREEN')) {
    const results = await runTests();
    await orchestrator.transition({ type: 'GREEN_PHASE_COMPLETE', testResults: results });
  } else {
    throw e;
  }
}

Prevention

When it happens

Trigger: Calling orchestrator.transition({ type: 'GREEN_PHASE_COMPLETE' }) without a testResults field; constructing the event object dynamically and omitting testResults when the test run produced no summary; a test runner integration that fails to attach its summary object to the event.

Common situations: Custom automation that fires phase events manually; a test runner wrapper returning undefined on runner crash so the summary never gets attached; refactoring event shapes after a version change where testResults became mandatory on GREEN_PHASE_COMPLETE.

Understand the failure class

Background: "Missing required field" and "field is required" errors: why libraries reject payloads that omit mandatory fields — this error's family across 20 libraries.

Related errors


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