kestra-io/kestra · error · TourSceneError

onboarding.tour.errors.no_execution_to_replay

Error message

onboarding.tour.errors.no_execution_to_replay

What it means

Thrown by the onboarding tour replay step when there is no execution to replay. replayFromFailedTask reads tour().failedExecutionId ?? tour().lastExecutionId; if both are null/undefined it cannot pick a source execution, so it throws TourSceneError with key 'onboarding.tour.errors.no_execution_to_replay'. This is a state-machine guard: the replay scene was entered without a prior execution being recorded in tour state.

Source

Thrown at ui/src/components/onboarding/tour/useTourActions.ts:291

    const executeFlow = async (flowId: string = TOUR_FLOW_ID) => {
        const execution = await executionsStore.triggerExecution({
            namespace: TOUR_NAMESPACE,
            id: flowId,
            kind: "NORMAL",
            formData: {},
            labels: [TOUR_MANUAL_LABEL],
        })
        tourStore.setTourState({lastExecutionId: execution.id})
        await openExecution(execution.id, flowId)
        return waitForExecution(execution.id)
    }

    // Replay, not restart: only replay copies successful task-run outputs, which the fixed message needs.
    const replayFromFailedTask = async () => {
        const executionId = tour().failedExecutionId ?? tour().lastExecutionId
        if (!executionId) {
            throw new TourSceneError("onboarding.tour.errors.no_execution_to_replay")
        }

        const execution = await executionsStore.loadExecution({id: executionId})
        const failedTaskRun = (execution?.taskRunList ?? []).find(
            (taskRun: any) => taskRun?.state?.current === "FAILED",
        )
        const revision = await latestRevision()

        const replayed = await executionsStore.replayExecution({
            executionId,
            taskRunId: failedTaskRun?.id,
            revision,
        })

        const replayedId = replayed?.id ?? executionId
        tourStore.setTourState({restartedExecutionId: replayedId, lastExecutionId: replayedId})
        await openExecution(replayedId)
        return waitForExecution(replayedId)

View on GitHub (pinned to 823fada927)

Solutions

  1. Ensure the execute-flow tour scene ran and produced an execution (lastExecutionId should be set in tour state).
  2. If tour state was lost, restart the tour or jump back to the execute-flow scene.
  3. Confirm the tour flow actually failed (a fully successful run leaves failedExecutionId unset).
Defensive patterns

Strategy: validation

Validate before calling

const executionId = tour().failedExecutionId ?? tour().lastExecutionId;
if (!executionId) {
  // route the user back to the execute-flow scene instead of throwing
  return router.push({name: 'onboarding/tour', query: {scene: 'execute_flow'}});
}

Try / catch

try {
  return await replayFromFailedTask();
} catch (e) {
  if (e instanceof TourSceneError && e.key.endsWith('no_execution_to_replay')) {
    guideUserToExecuteFlowScene();
    return;
  }
  throw e;
}

Prevention

When it happens

Trigger: replayFromFailedTask() is called while tour().failedExecutionId and tour().lastExecutionId are both falsy (no prior execution stored in tourState), so TourSceneError is thrown with no extra context.

Common situations: The user skipped the execute-flow scene, tour state was cleared (localStorage reset, different browser, tenant switch), the prior execution never reached a failed state so failedExecutionId was never set, or the tour was resumed on a stale link.

Related errors


AI-assisted analysis of kestra-io/kestra@823fada927 (2026-08-14). Data as JSON: /api/errors/9347a93bd6b92341. Report an issue: GitHub.