kestra-io/kestra · error · TourSceneError

onboarding.tour.errors.save_flow

Error message

onboarding.tour.errors.save_flow

What it means

Thrown by the onboarding tour when persisting the tour flow is blocked by validation. applySource writes the YAML source, calls flowStore.saveAll(), and if the outcome is 'blocked' it raises TourSceneError with key 'onboarding.tour.errors.save_flow' and a reason built from joined flow errors. 'blocked' means the store detected schema/validation errors and refused to save.

Source

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

            await FlowsAPI.createFlow({
                body: source,
                showMessageOnError: false,
            } as Parameters<typeof FlowsAPI.createFlow>[0])
            await flowStore.loadFlow({namespace: TOUR_NAMESPACE, id: TOUR_FLOW_ID})
        }
        await flowStore.initYamlSource()
        return flowStore.flow
    }

    const applySource = async (source: string) => {
        if (route.name !== "flows/create") {
            return saveSource(source)
        }

        await writeSource(source)
        const outcome = await flowStore.saveAll()
        if (outcome === "blocked") {
            throw new TourSceneError("onboarding.tour.errors.save_flow", {
                reason: flowStore.flowErrors?.join(" ") ?? "",
            })
        }
        await openFlowEditor()
        return flowStore.flow
    }

    const openEditorWith = async (source: string) => {
        await saveSource(source)
        await openFlowEditor()
        await flowStore.initYamlSource()
    }

    const latestRevision = async (id: string = TOUR_FLOW_ID) => {
        const flow = await flowStore.loadFlow({namespace: TOUR_NAMESPACE, id, store: false})
        return flow?.revision as number | undefined
    }

View on GitHub (pinned to 823fada927)

Solutions

  1. Inspect flowStore.flowErrors after the failure — the joined strings name the exact validation problems.
  2. Re-apply the canonical tour flow source for your Kestra version (the tour payload is version-pinned).
  3. Confirm all plugins referenced by the tour flow are installed and loaded.
  4. If a Kestra upgrade broke the bundled tour YAML, update the onboarding tour payload to match the new schema.
Defensive patterns

Strategy: validation

Validate before calling

// Validate before save
const outcome = await flowStore.saveAll();
if (outcome === 'blocked') {
  // do not throw yet; show errors and let the user fix
  surfaceFlowErrors(flowStore.flowErrors);
}

Try / catch

try {
  const outcome = await flowStore.saveAll();
  if (outcome === 'blocked') {
    throw new TourSceneError('onboarding.tour.errors.save_flow', {reason: flowStore.flowErrors?.join(' ') ?? ''});
  }
} catch (e) {
  if (e instanceof TourSceneError) { showFlowErrorDialog(e.reason); return; }
  throw e;
}

Prevention

When it happens

Trigger: In the tour, route is 'flows/create', writeSource(source) succeeds, flowStore.saveAll() returns 'blocked' (flowErrors non-empty), and TourSceneError is thrown with reason = flowStore.flowErrors.join(' ').

Common situations: The injected tour YAML got corrupted by an editor plugin or stray edit, a plugin task in the tour flow is missing (plugin not installed), the flow references an unknown property, or a Kestra version change made the bundled tour flow invalid.

Related errors


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