MGS3003: tool not on PATH
proc\which could not resolve a command. The tool is not installed, or not
visible to this run - a sandboxed target sees a curated PATH, so "installed on
your machine" and "reachable from here" are different questions.
[MGS3003] "docker" is not on PATH: exec: "docker": executable file not found in $PATH
Why this raises instead of returning ""
proc\which used to answer "" for a missing command so a magusfile could
branch on proc\which(cmd) == "". That put the check on every call site and made
it optional - skip it and the empty string flows straight into an proc\exec or
a path join, and the failure surfaces as something unrelated.
Resolution
Wrap it where a missing tool is a case you want to explain. The point of checking at all is to replace a cryptic exec failure with a sentence that says how to fix it:
try {
proc\which("docker");
} catch (e) {
throw "completion-test needs a docker daemon: it runs each shell's official image";
}
If the tool should always be present, do not catch. The raised error already names the command and the reason, which is a better failure than a downstream exec error nobody can trace back.
Pinning the tool instead
A tool a target needs should usually be pinned in mise.toml rather than
assumed. A pinned tool is installed by mise install in CI and resolves the
same way on every machine, which turns this diagnostic from a routine
occurrence into a genuine misconfiguration.
Catching it by code
try {
final p = proc\which("docker");
} catch (e) {
if (e["code"] == "MGS3003") {
magus\log.info("docker is not available; skipping the container checks");
}
}