eyaltoledano/claude-task-master · error

Invalid workflow state. State may be corrupted. Consider sta

Error message

Invalid workflow state. State may be corrupted. Consider starting a new workflow.

What it means

resumeWorkflow() loads persisted state and asks a fresh orchestrator whether the state can be resumed via canResumeFromState(state). When that validation fails — the phase is unknown/invalid for the context, the context is missing required fields, or the shape doesn't match expectations — the service throws, advising that the state file may be corrupted and a new workflow should be started.

Source

Thrown at packages/tm-core/src/modules/workflow/services/workflow.service.ts:269

		// Set main task status to in-progress
		await this.updateTaskStatus(taskId, 'in-progress', tag);

		return this.getStatus();
	}

	/**
	 * Resume an existing workflow
	 */
	async resumeWorkflow(): Promise<WorkflowStatus> {
		// Load state
		const state = await this.stateManager.load();

		// Create new orchestrator with loaded context
		this.orchestrator = new WorkflowOrchestrator(state.context);

		// Validate and restore state
		if (!this.orchestrator.canResumeFromState(state)) {
			throw new Error(
				'Invalid workflow state. State may be corrupted. Consider starting a new workflow.'
			);
		}

		this.orchestrator.restoreState(state);

		// Re-enable auto-persistence
		this.orchestrator.enableAutoPersist(async (newState: WorkflowState) => {
			await this.stateManager.save(newState);
		});

		// Initialize activity logger to continue tracking events
		this.activityLogger = new WorkflowActivityLogger(
			this.orchestrator,
			this.stateManager.getActivityLogPath()
		);
		this.activityLogger.start();

View on GitHub (pinned to c0c98d367c)

Solutions

  1. Inspect the workflow state file (stateManager path) and fix obvious corruption — invalid phase value, missing context fields, out-of-range currentSubtaskIndex — or restore it from backup.
  2. If the state is unrecoverable, delete the state file and start a new workflow with startWorkflow({ ..., force: true }).
  3. After upgrading the package, check the changelog for workflow state schema changes; migrate the old state or start fresh.
  4. Reproduce by calling stateManager.load() yourself and logging `state.phase` and `state.context` to see exactly which field fails validation in canResumeFromState().

Example fix

// before
await workflowService.resumeWorkflow(); // throws: state.context.subtasks missing
// after
const state = JSON.parse(fs.readFileSync(statePath, 'utf8'));
if (!state.context?.subtasks?.length) {
  fs.rmSync(statePath); // remove corrupted state
  await workflowService.startWorkflow({ taskId, taskTitle, subtasks, force: true });
} else {
  await workflowService.resumeWorkflow();
}
Defensive patterns

Strategy: try-catch

Validate before calling

const state = JSON.parse(fs.readFileSync(stateFilePath, 'utf8'));
const validPhases = ['INIT', 'PREFLIGHT', 'BRANCH_SETUP', 'SUBTASK_LOOP', 'FINALIZE', 'COMPLETE', 'ERROR'];
const valid =
  validPhases.includes(state?.phase) &&
  Array.isArray(state?.context?.subtasks) && state.context.subtasks.length > 0 &&
  typeof state?.context?.taskId === 'string' &&
  Number.isInteger(state?.context?.currentSubtaskIndex) &&
  state.context.currentSubtaskIndex >= 0 && state.context.currentSubtaskIndex <= state.context.subtasks.length;
if (!valid) {
  fs.rmSync(stateFilePath); // remove corrupted state, then start fresh
}

Type guard

function isValidWorkflowState(state: unknown): state is { phase: string; context: { taskId: string; subtasks: unknown[]; currentSubtaskIndex: number } } {
  const s = state as any;
  return (
    !!s && typeof s.phase === 'string' &&
    typeof s.context?.taskId === 'string' &&
    Array.isArray(s.context?.subtasks) && s.context.subtasks.length > 0 &&
    typeof s.context?.currentSubtaskIndex === 'number' &&
    Number.isInteger(s.context.currentSubtaskIndex) &&
    s.context.currentSubtaskIndex >= 0
  );
}

Try / catch

try {
  await workflowService.resumeWorkflow();
} catch (err) {
  if (err instanceof Error && err.message.includes('Invalid workflow state')) {
    // state is unrecoverable; start fresh
    await workflowService.startWorkflow({ ...options, force: true });
  } else {
    throw err;
  }
}

Prevention

When it happens

Trigger: Calling workflowService.resumeWorkflow() (or the `resume` command) where orchestrator.canResumeFromState(state) returns false for the state loaded by stateManager.load(): e.g. state.phase is not a valid WorkflowPhase, state.context.subtasks is missing/empty, currentSubtaskIndex is out of bounds, or the JSON was truncated/manually edited.

Common situations: State file truncated by a crash mid-write or full disk; manual editing or a script rewriting the state JSON; resuming a state saved by an older package version whose phase names/context schema changed after an upgrade; the file being committed/shared across machines and mangled (line endings, merge conflicts); deleting or renaming the branch the state references while phase validation requires it.

Related errors


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