mastra-ai/mastra · error
This workflow run is still running, cannot time travel
Error message
This workflow run is still running, cannot time travel
What it means
Thrown by the workflow time-travel API when the loaded snapshot's status is still 'running'. Time travel requires a terminal or suspended state because mutating the step history of an in-flight run would conflict with its active execution. The library refuses to rewind a run that the engine still considers live.
Source
Thrown at packages/core/src/workflows/workflow.ts:4882
actor?: ActorSignal;
} & Partial<ObservabilityContext>): Promise<WorkflowResult<TState, TInput, TOutput, TSteps>> {
const observabilityContext = resolveObservabilityContext(rest);
if (!stepParam || (Array.isArray(stepParam) && stepParam.length === 0)) {
throw new Error('Step is required and must be a valid step or array of steps');
}
const workflowsStore = await this.#mastra?.getStorage()?.getStore('workflows');
const snapshot = await workflowsStore?.loadWorkflowSnapshot({
workflowName: this.workflowId,
runId: this.runId,
});
if (!snapshot) {
throw new Error(`Snapshot not found for run ${this.runId}`);
}
if (snapshot.status === 'running') {
throw new Error('This workflow run is still running, cannot time travel');
}
let steps: string[];
let newStepParam = stepParam;
if (typeof stepParam === 'string') {
newStepParam = stepParam.split('.');
}
steps = (Array.isArray(newStepParam) ? newStepParam : [newStepParam]).map(step =>
typeof step === 'string' ? step : step?.id,
);
let inputDataToUse = inputData;
if (inputDataToUse && steps.length === 1) {
inputDataToUse = await this._validateTimetravelInputData(inputData, this.workflowSteps[steps[0]!]!);
}
const timeTravelData = createTimeTravelExecutionParams({View on GitHub (pinned to 75dd419e61)
Solutions
- Wait for the run to reach a terminal/suspended status, or await the run's completion promise before time traveling.
- If the run is actually dead (crash/restart), manually mark the stale snapshot status (e.g., 'failed') in the store, then retry.
- Resume a suspended run via resume() instead of time traveling.
- Cancel/stop the run through the workflow API so its snapshot status is updated, then time travel.
Example fix
// before
await workflow.timeTravel(runId, 'step1'); // throws if still running
// after
const snapshot = await store.loadWorkflowSnapshot({ workflowName: wf.id, runId });
if (snapshot.status === 'running') await runCompletion; // or cancel the run first
await workflow.timeTravel(runId, 'step1'); Defensive patterns
Strategy: try-catch
Validate before calling
const snapshot = await store.loadWorkflowSnapshot({ workflowName: workflowId, runId });
if (snapshot?.status === 'running') throw new Error(`Run ${runId} still in progress`); Try / catch
try { await workflow.timeTravel(runId, step); } catch (e) { if ((e as Error).message.includes('still running')) { await waitForRunTerminal(runId); /* retry once */ } else throw e; } Prevention
- Await the run's result/completion before time traveling.
- On server restart, reconcile stale 'running' snapshots to a terminal status.
- Prefer resume() for suspended runs instead of time travel.
When it happens
Trigger: Calling time travel on a run whose persisted snapshot has status === 'running' — i.e., the run hasn't finished (or a previous run crashed without updating its snapshot status to a terminal value).
Common situations: Time traveling concurrently with an active run; a crashed/restarted server left stale snapshots with status 'running'; a hung step (e.g., awaiting an external event or long suspend) keeps the run marked running.
Related errors
- WORKFLOW_RESUME_ALREADY_CLAIMED
- error.message (workflow resume already claimed conflict)
- Agent "${agentId}" is already connected to Slack. Disconnect
- Agent "${agentId}" is already connected to Telegram. Disconn
- No Telegram installation found for agent "${agentId}"
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/14a34a0caf85e100.
Report an issue: GitHub.