Depends On

Last updated on October 28, 2026

You can control execution order between phases using the depends_on parameter.

main:
  - name: Power On
    key: power_on
    python: phases.power_on

  - name: Test WiFi
    key: test_wifi
    python: phases.test_wifi
    depends_on: [power_on] 

  - name: Test Bluetooth
    key: test_bluetooth
    python: phases.test_bluetooth
    depends_on: [power_on] 

  - name: Final Check
    key: final_check
    python: phases.final_check
    depends_on: [test_wifi, test_bluetooth] 

TofuPilot waits for all dependencies to complete before executing a phase. Dependencies reference phase keys, not phase names.

Phases Without Dependencies

A phase without depends_on does not wait for the phase above it. TofuPilot starts phases in file order, as many at a time as there are free workers (8 by default). With fewer than 8 independent phases, they all start together.

For a bench where phases share one instrument or one link (a serial port, a MAVLink connection, a power supply), run them one after another, either with workers: 1 or by chaining depends_on:

execution:
  workers: 1 # phases run one at a time, in file order (a retry waits its turn)

When a phase fails under on_first_failure: stop (the default), phases that have not started are cancelled, phases already running finish, and teardown phases still run. See On Fail.

Validation

TofuPilot validates dependencies to prevent execution errors:

  • Circular dependencies: Detects and prevents cycles (e.g., A waits for B, B waits for A) in setup, main and teardown
  • Orphaned dependencies: Errors if a phase depends on a non-existent phase key, in any stage
  • Later stage: Errors if a phase depends on a phase of a later stage (a setup phase waiting for a main phase, a shared scope: execution setup waiting for a per-slot setup)
  • Maximum dependencies: Each phase can have up to 100 dependencies

A dependency on an earlier stage is accepted and redundant: setup always completes before main, and main before teardown. A dependency on a phase further down the same stage is honoured: the order in the file does not matter.

The procedure lint (shown in Studio) also warns when a Python phase parameter without a default names another phase whose result it will not receive: one that is neither in its depends_on nor in an earlier stage, or, for a shared scope: execution setup or teardown phase, any per-slot phase (a shared phase only receives shared results). The warning says why the result is not available and what to change. The run would fail that phase at start; a parameter with a default receives its default instead (see Previous Results).

How is this guide?

On this page