The robot

robot-paths: site overlay, colon, empty slot that means the defaults

A bare .eb name is a query. The empty element after the colon is where the shipped defaults go.

robot path to easyconfig to easyblock to dependencies

A bare filename is a query. The robot walks a path and returns a working order.

bare name searched in site paths then defaults

A bare .eb is not a path. The robot walks --robot-paths, site first when the colon form is used.

Questions

  • What is a bare .eb filename, if it is not a path?

  • Where do the defaults go in --robot-paths=/my/site:?

  • Which list is the site’s, not EasyBuild’s?

What you will be able to do

  1. Say what a bare easyconfig filename is, and what resolves it.

  2. Read a --robot-paths value and say which element is the shipped EasyBuild defaults.

  3. Name the three lists the robot consults, and say which one is not EasyBuild’s to set.

The command is this:

eb GROMACS-2025.2-foss-2025a.eb -r

One file is named. One package is requested. Dozens of modules appear in a working order. Most are never named at the prompt. The -r caused this. It is short for --robot. This page explains its function. It also explains its search locations. The sample is a toy robot. It walks a canned universe bundled with the page. It does not walk the site. Change Python from 3.13.1 to 3.11.3 to observe a dependency being removed.

name = 'GROMACS'
version = '2025.2'
toolchain = {'name': 'foss', 'version': '2025a'}

dependencies = [
 ('Python', '3.13.1'),
 ('FFTW', '3.3.10'),
]

builddependencies = [
 ('CMake', '3.31.4'),
]

A filename is a query

Begin with a smaller appearance. The command passed GROMACS-2025.2-foss-2025a.eb contained no path, and the working directory did not contain it. That works. EasyBuild resolves it against an ordered list of directories, the robot path, and resolves every discovered dependency in the same manner. No distinction in kind separates “find the requested easyconfig” from “find a dependency of the requested easyconfig”. The same query yields the same path. The relevant question is never “why can EasyBuild not find the dependency”. The relevant question is “what is on the robot path”.

The robot path, and the empty element

--robot-paths determines the setting. The default consists of the easyconfigs supplied with the EasyBuild installation. The default enables a fresh installation to build thousands of packages without additional configuration. The next portion may appear as a typo; it is intentional. For example, a legal and common method to set the option:

--robot-paths=/my/site/easyconfigs:

Trailing colon is intentional. Omitting colon inverts meaning. Without colon, default robot path is replaced by a single directory. EasyBuild then finds none of the thousands of easyconfigs it includes. With colon, EasyBuild searches that directory first. EasyBuild retains default paths thereafter. Mechanism is neither a special case nor a parsing quirk. The option is declared with action add_flex. Documentation in easybuild/base/generaloption.py explains behavior:

similar to add / add\_first, but replaces the first "empty" element with
the default

The colon-separated list /my/site/easyconfigs: contains two elements. The second element is empty. add_flex inserts the default into the empty element. The colon is a position rather than punctuation. The colon indicates where the defaults should be placed. Placing the colon at the front, :/my/site/easyconfigs, makes EasyBuild search the site directory last. The behavior becomes visible. The value defines an order. The blank marks the default’s position within the order. Paths supplied to --robot are placed ahead of --robot-paths. The framework states this explicitly. The comment reads “paths specified to --robot have preference over --robot-paths”.

EB-Robot-1 — Where do the defaults go

Three settings, one of them wrong for almost every purpose:

A. --robot-paths=/my/site/easyconfigs
B. --robot-paths=/my/site/easyconfigs:
C. --robot-paths=:/my/site/easyconfigs
  1. For each, say where EasyBuild looks and in what order.

  2. Which one leaves a fresh install unable to find any of the thousands of easyconfigs it came with?

  3. You want your directory consulted only when the defaults have nothing. Which do you pick?

Solution

The value is a colon-separated list, and the empty element is where the defaults are inserted. That is the whole rule, and everything else follows from it.

A has one element and no empty one, so the defaults have nowhere to go and your directory replaces them. That is the answer to question 2, and it is the common mistake: the robot no longer sees every package EasyBuild ships with.

B has two elements, the second empty, so it reads: yours, then the defaults. That is the common site layout.

C also has two, the first empty: defaults, then yours. That answers question 3, and it is the right shape when your directory contains a fallback rather than an override.

Why an overlay is the normal case

Sites almost always maintain their own easyconfigs directory before the defaults. The reason is A pin is for one generation’s closing point: an EasyBuild release carries a fixed set of easyconfigs. Any easyconfig merged upstream after that release is not included. When a site requires a package newer than its EasyBuild, it must have a place for that easyconfig. The location is placed first on the robot path. The freeze creates two statements that are simultaneously true. Remembering this point is important.

  • The easyconfig exists upstream, merged, on the development branch.

  • The site cannot build it, and its EasyBuild has never heard of it.

Both statements are true. The remedy is not to dispute the first statement. Instead, place a copy where the robot looks, or direct the robot to the commit that added it.

How it decides an order

The robot returns an executable order given the path. No component is built before its dependencies. The order is not computed from a completed graph. The graph is discovered during the process. resolve_dependencies in easybuild/tools/robot.py runs a loop. The loop’s shape explains most of the output of --dry-run. One pass asks which easyconfigs are fully resolved. A fully resolved easyconfig has every declared dependency already available. Those easyconfigs are placed at the end of the order. The robot treats newly ordered easyconfigs as available. By the time each easyconfig is built it is available. For any unresolved dependency, the robot searches the robot path for an easyconfig that provides it. The robot adds the found easyconfig to the set being resolved. The process repeats. Step 3 often surprises users. The set of things being resolved grows during resolution. That explains why --dry-run lists packages never named and never queried.

Available means what the module tool says

Step 1 enables available. The function states its source directly.

avail_modules = modtool.available()

The robot queries the module system for installed modules. The plan depends on MODULEPATH as much as on the robot path. These are two distinct lists configured in separate ways. A dependency that is already installed is considered satisfied. It does not appear in the order. Two results follow. Both are useful. A build plan is not portable. Executing the same command on a machine with a different set of installed modules yields a different, yet equally correct, plan. --dry-run on a well‑stocked cluster is short for a reason. It does not report that the package has few dependencies. It reports that most dependencies are already present. EasyBuild 5 dropped the implication that -D includes --robot. eb pkg.eb -D dry‑runs only the named file. The resolved plan is eb pkg.eb -Dr. A wrapper is the range EasyBuild will not write is the page for that change. -D / --dry-run-short prints the plan. From EasyBuild 5 it does not retain missing dependencies; that was an EasyBuild 4 default. It marks each one [x] or [ ] once -r is also on the command line. No eb --retain-all-deps exists; that name is an internal argument used by -D, --dep-graph and --check-conflicts. -M / --missing-modules prints only the absent set.

What is being rebuilt does not satisfy anything

Loop details are easy to miss. A loop detail can save an afternoon.

being_installed = [p['full_mod_name'] for p in easyconfigs]
avail_modules = [m for m in avail_modules if m not in being_installed]

Anything in this run’s own list is removed from the available set, even when installed. Requesting a rebuild of a library and a dependent library rebuilds both, in that order. The old library does not satisfy the dependent. A matching escape hatch exists. A dependency marked as an external module has no easyconfig. The robot does not search for one. The module must still be available. If the module is not available, the resolve loop ends with Missing modules for dependencies marked as external modules. A site informs the robot about a module EasyBuild did not build. The site does not pretend the module exists.

The order is not unique

Any topological ordering of the discovered graph is valid. EasyBuild does not promise a particular ordering. The list generated by --dry-run is an answer rather than the definitive answer. Diffing two such lists across versions shows churn lacking meaning. A toolchain is a sibling of a hierarchy. Sibling toolchains convey the same fact one level lower.

And the hierarchy filters the candidates

The hierarchy from A toolchain is a hierarchy determines which items step 3 may locate. A candidate is valid only when its toolchain belongs to the package’s hierarchy. The filter represents the intersection of the two pages. The filter generates the most frustrating class of robot failure. The module is installed. module avail lists the module. The robot reports it cannot find the module. The robot does not lie. The robot reports that nothing in the package’s hierarchy provides that dependency. A module built with a toolchain outside that hierarchy is invisible rather than rejected.

EB-Robot-2 — The same command, two different plans

You run the same command with -D on two machines, from the same easyconfig and the same robot path:

eb GROMACS-2025.2-foss-2025a.eb -r -D

On the cluster it lists three things to build. On your laptop it lists ninety.

  1. What differs, given that the robot path is the same?

  2. The cluster lists three. The laptop lists ninety. What on the cluster, not a flag, makes the difference?

Solution

MODULEPATH. The robot asks the module system what is installed, through modtool.available(), and treats anything already there as satisfied. The cluster has eighty-seven of those dependencies installed and your laptop has none.

So a build plan is a property of the machine as much as of the easyconfig, and it does not travel between them. The robot path decides what can be found; MODULEPATH decides what counts as already built.

-D prints the plan and marks each item. From EasyBuild 5 it does not retain missing dependencies. No eb --retain-all-deps. Use -Dr when the question is the full closure, and -M when the question is what is absent on this machine.

Ask before the build

The robot announces its decision. The robot does not perform it.

eb GROMACS-2025.2-foss-2025a.eb -r -D

Option -D is --dry-run-short (short paths). --dry-run prints full paths. The resolved list includes a marker beside each entry showing installed status or build requirement. Read the list before each non‑trivial build for a specific reason. The typed command hides the difference between installing two items and installing ninety items. That difference resembles the gap between a coffee and an afternoon. It provides the quickest detection of a dependency resolving to an unexpected version. This occurs most often when a site overlay shadows an upstream easyconfig with the same name.

Three lists, and a loop

The robot consults three lists. Confusing them leads to most errors.

List

Set by

Decides

the robot path

--robot-paths, empty element for the defaults

which easyconfigs can be found

MODULEPATH

your module system, not EasyBuild

what counts as already built

the toolchain hierarchy

A toolchain is a hierarchy, computed

which found candidates are eligible

It iterates with a loop rather than a graph traversal. It takes each fully resolved item. It marks it as available. It searches the path for missing items. It repeats. The resolved set expands during execution. --dry-run lists packages that were never requested. Two results deserve attention. A plan lacks portability. Items present in the current run’s list cease to count as available. Both a library and its dependents are rebuilt. Consult -Dr prior to any non‑trivial build. EasyBuild 5 -D is not the robot. This option uniquely differentiates one installation from ninety. The following page covers versionsuffix. versionsuffix appears as a constraint and as a label.

What to remember

  • A filename is a query against the robot path.

  • EasyBuild 5: -D does not imply -r. The plan is -Dr.

  • resolve_dependencies discovers the graph while it walks; it does not sort a finished graph.