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
- 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.
- If the state is unrecoverable, delete the state file and start a new workflow with startWorkflow({ ..., force: true }).
- After upgrading the package, check the changelog for workflow state schema changes; migrate the old state or start fresh.
- 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
- Back up the workflow state file before upgrading the package or hand-modifying it.
- Don't commit the state directory to git; merge conflicts corrupt the JSON.
- After any crash, validate the state JSON parses and has the expected shape before resuming.
- Check release notes for workflow state schema changes between versions; migrate or restart.
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
- Test results required for RED phase transition
- Test results required for GREEN phase transition
- GREEN phase must have zero failures
- All subtasks for task ${taskId} are already completed. Nothi
- MFA_VERIFICATION_FAILED
AI-assisted analysis of eyaltoledano/claude-task-master@c0c98d367c (2026-08-29).
Data as JSON: /api/errors/f005fa0b9f7f6f86.
Report an issue: GitHub.