Command: doctor
mads doctor (mads-doctor) is a tool designed to help users spot possible issues and solutions they may encounter when setting up a network of MADS agents.
This command has been introduced in MADS v2.4.1.
Description
mads-doctor is MADS’s answer to ros2 doctor/brew doctor: a single command that checks the things that most commonly go wrong in the first hour of using a pub-sub framework — a wrong broker URI, a stale settings file, a plugin protocol mismatch, a port already in use — and reports each one as [PASS], [WARN], or [FAIL] with a one-line fix hint. It never starts a broker or an agent, never calls a plugin’s process()/get_output()/load_data(), and never writes anything except the one narrow case --fix and --graph cover.
By default it checks, in order:
- Settings file found and parses. The path given by --settings (default
mads.iniin the current directory — unlike every other mads-* executable, whose-s/--settingsdefaults to a broker URI, since checking a local file is the point of this check) exists and is valid TOML. Atcp://...value is treated as a remote broker URI instead of a local file, and this check is reported [PASS] with a note pointing at the broker-reachable check below. - Broker reachable. Probes the broker’s settings endpoint (from --broker, else the
[broker]section’ssettings_address, elsetcp://localhost:9092) the same waymads up’sready = "broker"does. - Declared plugin(s) resolve and load. Every
attachmentkey found in the settings file (or every --plugin path given explicitly, which then takes priority) is dry-run loaded through the samepugg::Kernelpath mads-source/mads-filter/mads-sink use — loaded, itskind()and protocol read, then unloaded.process()/get_output()/load_data()are never called. - Plugin protocol matches the pinned
mads_pluginversion. Compares each loaded plugin’s protocol againstshare/plugin_deps.json’splugin_protocol(the versionmads plugin --updatemigrates plugins to). - CURVE key files, if --crypto** is given, exist and are well-formed.** Checks
<key_client>.key/.puband<key_broker>.pubunder --keys_dir — the same three filesMads::CurveAuth::setup_curve_client()reads — exist and decode as valid Z85 CURVE keys. - Local port-availability sanity check. Probes the settings file’s
[broker]frontend_address/backend_address/settings_addressports on127.0.0.1; a port already answering is reported as a likely broker-already-running collision.
mads-doctor exits 0 only if every check reported [PASS] or [WARN]; any [FAIL] makes it exit 1.
Carefully read the messages: your setup might be perfectly OK even if the tool reports some failure. For example, you might have installed a non-compatible plugin, which is never loaded by your setup, thus you can safely neglect the corresponding [FAIL] or [WARN] message.
--plan
--plan director.toml is a standalone mode: it parses, validates and expands the given director.toml through the exact same src/director_config.hpp module mads up --dry-run uses (no process spawning), and prints the same kind of expanded-plan report — start order, templated command, scale expansion, after dependencies, ready probes. It ignores every other flag except --settings-independent behaviour: the settings file, broker, plugins, and CURVE keys are not touched. Use it to sanity-check a whole deployment before running mads up for real.
--graph
--graph[=file.dot] is another standalone, read-only mode: it parses the settings file (the same --settings path used by check 1, reusing the same TOML-loading logic) and emits a Graphviz DOT description of the pub/sub topology it declares, to file.dot if given, or to standard output otherwise. It never probes the broker, plugins, ports, or CURVE keys, and never shells out to a dot binary — rendering the DOT text to an image is left to the user (e.g. mads doctor --graph | dot -Tpng -o topology.png).
Every non-[agents]/non-[broker] section becomes one record-shaped node, named after the section, with its sub_topic entries listed underneath (one per line; sub_topic = [""] — subscribe-all —- renders as a single (all) line; no subscriptions renders no compartment). One edge is drawn for every section A’s pub_topic and every other section B’s sub_topic pattern that matches it (per Mads::topic_match(), the same MQTT-style wildcard matcher Agent::connect_sub() uses at runtime), labeled with A’s pub_topic. Nodes are colored by inferred role: a source (pub_topic only) is darkred, a filter (both) is darkgreen, a sink (sub_topic only) is darkblue; an agent with neither gets no color attribute. A node gets a dashed contour if it has a dangling topic — a pub_topic nothing subscribes to, or a sub_topic pattern nothing ever publishes to — which is usually a misconfiguration worth a second look. An agent’s own pub_topic matching its own sub_topic (a self-loop) satisfies both sides and is not flagged as dangling, matching real broker behavior.
For example, the following mads.ini file:
[agents]
frontend_address = "tcp://localhost:9090"
backend_address = "tcp://localhost:9091"
settings_address = "tcp://localhost:9092"
timecode_fps = 25
[broker]
frontend_address = "tcp://*:9090"
backend_address = "tcp://*:9091"
settings_address = "tcp://*:9092"
[logger]
mongo_uri = "mongodb://localhost:27017"
mongo_db = "blescan_roadside2"
sub_topic = ["ble_scan", "ble_filter"]
[ble_scan]
pub_topic = "ble_scan"
[ble_filter]
sub_topic = ["ble_scan"]
pub_topic = "ble_filter"
[feedback]
# Subscribes to ALL topics
sub_topic = ["ble_filter"]
[rerunner]
sub_topic = ["ble_filter", "arduino"]
keypaths = [.. list of keypaths ...]
recording_id = "rec_ble"
[arduino]
pub_topic = "arduino"
port = "/dev/cu.usbmodem34B7DA5F9A5C2"
baudrate = 115200produces:
Note that pub_topic and sub_topic are optional in the INI file: pub_topic defaults to the agent name, and sub_topic defaults to an empty list.
To have the graphviz correctly drawn, though, you have to explicitly set the pub_topic field, because this is the only way the tool has to distinguish source and filter agents to pure sink agents.
In other words, a source agent with no explicit pub_topic will be rendered to Graphviz as a dangling agent, even though it will correctly run and publish on its name’s topic.
--fix
--fix attempts the one check with an unambiguous, non-destructive auto-fix: if the settings file is missing, it is scaffolded from the same template mads ini renders. --fix only ever creates a missing file — it never deletes or overwrites an existing one, however broken.
Options
- -s, --settings path
-
Path to the settings file to check. Default
mads.iniin the current directory. Atcp://...value is treated as a remote broker URI instead. - --broker uri
-
Broker settings endpoint to probe for check 2. Default: derived from the settings file’s
[broker]section, elsetcp://localhost:9092. - --timeout ms
-
Timeout in milliseconds for the broker-reachable and port-availability probes. Default
1000. - --plugin path
-
Dry-run load this plugin file (repeatable). When given, replaces the automatic scan of the settings file’s
attachmentkeys. Resolved like mads-source/-filter/-sink’s ownpluginargument: relative to the current directory first, falling back to the installed-plugin location. - --crypto
- Also run the CURVE key-file check (check 5). Off by default, since CURVE is opt-in.
- --keys_dir dir
-
Directory to look for CURVE key files in. Default:
<exec_dir>/../etc, same as every other mads-* executable’s--keys_dir. - --key_broker name
-
Base name (without
.pub) of the broker/server CURVE public key file. Defaultbroker. - --key_client name
-
Base name (without
.key/.pub) of the client CURVE key files. Defaultclient. - --plan director.toml
-
Validate a
director.tomldeployment plan (likemads up --dry-run) and exit; see above. - --graph[=file.dot]
- Emit a Graphviz DOT topology graph of the settings file’s declared pub/sub topics to file.dot, or standard output if omitted, and exit; see above.
- --fix
- Attempt safe, non-destructive auto-fixes; see above.
- -v, --version
- Show version information.
- -h, --help
- Show summary of options.
Exit status
0 if every check reported [PASS] or [WARN] (or, in --plan mode, if the plan loaded and expanded cleanly). 1 if any check reported [FAIL], or --plan’s file failed to load/validate.
Examples
Check the settings file in the current directory, plus broker reachability and port availability:
mads doctorCheck a specific settings file and CURVE keys, scaffolding the file if it is missing:
mads doctor -s /etc/mads/mads.ini --crypto --fixSanity-check a whole deployment plan before running it for real:
mads doctor --plan deploy/director.tomlPrint the declared pub/sub topology as DOT text, and render it to an image with Graphviz:
mads doctor --graph | dot -Tpng -o topology.pngWrite the topology graph straight to a file instead:
mads doctor --graph=topology.dot