Debugging flows

Use test runs, execution logs, and step inspection to find and fix Flow errors.

Test a Flow

Use a test run to reproduce a problem with controlled inputs. The test uses the current unsaved steps, so you can test a change before you save the Flow.

To test a Flow, follow these steps:

  1. In the Flow editor toolbar, click Run flow. The Run Flow sheet opens.
  2. In the Run Flow sheet, choose Test.
  3. In the Test view, enter the input values for the Flow.
  4. To include outputs from hidden steps, open the execution mode menu and choose Run in debug mode. The Test view uses debug mode by default.
  5. Click Run Flow. The execution results appear in the sheet.
  6. Review each step’s input, output, status, and execution time when available.

After the run completes, click Save as test case. Review the input and expected answer in the dialog, then click Save case. The dashboard creates the Flow’s default eval suite if it does not exist.

Inspect execution logs

Use the Logs page to inspect completed and failed Flow executions. To inspect an execution, follow these steps:

  1. Open Logs in the sidebar.
  2. Use the search field or filters to find the Flow execution.
  3. Select the execution.

The execution details include the following information:

  • A timeline with each step’s status and duration.
  • A step inspector with the step’s input, output, and configuration.
  • Error messages and stack traces when they are recorded.
  • Variable values from the execution when they are recorded.

For more information, see Working with logs.

Inspect step results

Use the execution results to compare what each step received with what it returned. Select a step to review its input, output, duration, and status. This comparison helps you identify the step that fails or produces unexpected output.

Resolve common errors

Use these checks to diagnose common Flow errors.

Undefined variable

If you see Cannot read property 'output' of undefined, check that the referenced outputVariable exists and that its step runs before the reference. Check the spelling of the outputVariable and confirm that the referenced step runs first.

API call failure

If you see Request failed with status 401, verify the API key, endpoint, and request headers. Check the external service’s authentication requirements before you run the Flow again.

Timeout

If a step times out, compare its duration with the timeout value. A run races three independent budgets, and the shortest one that applies wins:

BudgetDefaultOverride
Per step5 minutesoptions.stepTimeoutMs, 1000–600000 ms attached or 1800000 ms with Prefer: respond-async
Per Flow15 minutesoptions.flowTimeoutMs, 1000–900000 ms attached or 1800000 ms with Prefer: respond-async
Whole agent5 minutesnot configurable

The 15 minute figure is the default value and attached-request maximum of the configurable flowTimeoutMs deadline. A Flow detached with Prefer: respond-async can raise it to 30 minutes. The whole-agent budget is a separate application wall-clock deadline, not the Cloudflare Workers CPU limit. Waiting for models and tools consumes that budget; asynchronous delivery alone does not remove it. The Flow deadline wins even when it is shorter than the step timeout, so a 5 minute step inside a 1 minute Flow aborts after 1 minute.

One step type has a much smaller default: an execute-agent step defaults to a 30 second timeout, while a prompt step defaults to 5 minutes. Set config.timeout in milliseconds on the execute-agent step when the child agent needs longer.

Reduce the work in the step or raise the relevant timeout when the step needs more time.

Invalid JSON

If a request body or transform-data step returns invalid JSON, validate the JSON syntax. Quote string values and remove trailing commas before you run the Flow again.

Inspect variable values

Add a transform-data step that returns the variables you want to inspect. Reference an earlier step by its outputVariable name:

1return {
2 logged: true,
3 customer_data_value: customer_data,
4 total_value: calculate_total,
5}

Replace customer_data and calculate_total with the outputVariable names in your Flow. Review the returned values in the execution results.

Test incrementally

To isolate a failing change, add and test steps in sequence:

  1. Add the first step and test the Flow.
  2. Add the second step and test the Flow again.
  3. Continue until a step changes the result.

Keep complex logic in separate transform-data steps when you need to inspect intermediate values.

Use default values

Use default values when a variable can be null or undefined. Add fallbacks with || or ??:

{{customer_data.tier || "standard"}}
{{order_history.count || 0}}

Replace customer_data and order_history with the relevant outputVariable names. The || operator uses a truthy fallback. The ?? operator uses a fallback only for null or undefined.

Test empty inputs, null values, large datasets, and invalid data to cover edge cases.

Test conditional branches

Run the Flow with inputs that select each branch:

  1. Run the Flow with input that makes the condition true.
  2. Confirm that the if branch runs.
  3. Run the Flow with input that makes the condition false.
  4. Confirm that the else branch runs.

Check that every variable in the condition exists and has the expected type.

Debug performance

If a Flow takes longer than expected, use execution logs to compare step durations. To reduce execution time, use these practices:

  • Identify the step with the longest duration.
  • Choose a model that matches the task’s latency needs.
  • Reduce prompt length.
  • Simplify transform-data steps.
  • Remove unnecessary steps.

Validate inputs

Validate required inputs at the start of a Flow. To stop the Flow when validation fails, set the transform-data step’s error handling to Stop on error, then return a validation result for valid input:

1if (!customerId) {
2 throw new Error('Customer ID is required')
3}
4
5return { validated: true }

Replace customerId with the input variable that your Flow requires. The step throws an error for missing input and returns { validated: true } for valid input.

Next steps