eyaltoledano/claude-task-master · error
Workflow state file not found at ${this.statePath}
Error message
Workflow state file not found at ${this.statePath} What it means
WorkflowStateManager.load() reads the workflow state JSON from `this.statePath` and throws a plain Error `Workflow state file not found at <path>` when the read fails with ENOENT. It signals that no workflow state has been persisted yet (or the configured path is wrong), as opposed to a corrupt/unreadable file.
Source
Thrown at packages/tm-core/src/modules/workflow/managers/workflow-state-manager.ts:121
async exists(): Promise<boolean> {
try {
await fs.access(this.statePath);
return true;
} catch {
return false;
}
}
/**
* Load workflow state from disk
*/
async load(): Promise<WorkflowState> {
try {
const content = await fs.readFile(this.statePath, 'utf-8');
return JSON.parse(content) as WorkflowState;
} catch (error: any) {
if (error.code === 'ENOENT') {
throw new Error(`Workflow state file not found at ${this.statePath}`);
}
throw new Error(`Failed to load workflow state: ${error.message}`);
}
}
/**
* Save workflow state to disk
* Uses steno for atomic writes and automatic queueing of concurrent saves
*/
async save(state: WorkflowState): Promise<void> {
try {
// Ensure writer is initialized (creates directory if needed)
await this.ensureWriter();
// Serialize and validate JSON
const jsonContent = JSON.stringify(state, null, 2);
// Validate that the JSON is well-formed by parsing it backView on GitHub (pinned to c0c98d367c)
Solutions
- Call `await stateManager.save(...)` at least once (or the workflow bootstrap that creates it) before load
- Verify the process cwd/project root matches where the state file was written; fix statePath configuration
- Call `existsSync(statePath)` or try/catch ENOENT and treat as 'no state yet' with a default state instead of crashing
Example fix
// before
const state = await stateManager.load(); // throws on fresh checkout
// after
let state;
try {
state = await stateManager.load();
} catch (e) {
if (String(e.message).includes('not found')) state = DEFAULT_WORKFLOW_STATE;
else throw e;
} Defensive patterns
Strategy: fallback
Validate before calling
import { existsSync } from 'fs';
if (!existsSync(statePath)) {
state = DEFAULT_WORKFLOW_STATE; // skip load entirely
} else {
state = await stateManager.load();
} Type guard
const isNotFound = (e: unknown) =>
e instanceof Error && e.message.includes('Workflow state file not found'); Try / catch
let state: WorkflowState;
try {
state = await stateManager.load();
} catch (e) {
if (isNotFound(e)) state = DEFAULT_WORKFLOW_STATE;
else throw e;
} Prevention
- Save workflow state once at workflow start so load never ENOENTs
- Don't gitignore/delete the state file if it is required across runs — or handle absence explicitly
- Confirm process cwd/project root matches the statePath configuration
- In CI/fresh checkouts, always treat missing state as first-run, not fatal
When it happens
Trigger: Calling `await stateManager.load()` before the workflow has ever been saved; statePath configured to a different project/directory than where state was saved; the state file was deleted (clean, git clean, CI fresh checkout).
Common situations: Fresh clone or CI run with no persisted workflow state; switching worktrees/branches where .taskmaster state is gitignored; typo'd project root so statePath points at a non-existent directory.
Understand the failure class
Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.
Related errors
- Failed to load workflow state: ${error.message}
- Failed to save workflow state: ${error.message}
- Failed to create backup: ${error.message}
- Failed to delete workflow state: ${error.message}
- Failed to list backups: ${error.message}
AI-assisted analysis of eyaltoledano/claude-task-master@c0c98d367c (2026-08-29).
Data as JSON: /api/errors/b57ad7e9ee9177a3.
Report an issue: GitHub.