magus v0.3.0 is out. See what's new
¶ View markdown source · ✎ Suggest an edit
1 min read

MGS3003: tool not on PATH

os\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] "vhs" is not on PATH: exec: "vhs": executable file not found in $PATH

Why this raises instead of returning ""

os\which used to answer "" for a missing command so a magusfile could branch on os\which(cmd) == "". That put the check on every call site and made it optional - skip it and the empty string flows straight into an os\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 {
    os\which("vhs");
} catch (e) {
    throw "tapes: vhs not found on PATH; install it with `brew install vhs`";
}

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 = os\which("docker");
} catch (e) {
    if (e["code"] == "MGS3003") {
        magus\info("docker is not available; skipping the container checks");
    }
}
MGS3003pathtoolshost-moduleserrorsmagusfile
Last updated (a170f9b2)
Glossary

Magusfile

The magusfile.buzz that declares a project's targets (as export funs) and binds its spells. See targets.

Target

A named operation (build, test, ...) you invoke with magus run <target>; it may compose a spell's tool-native operations and depend on other targets. See targets.

Module

A magus stdlib namespace a magusfile imports for host capabilities: filesystem, exec, vcs, and more. See the module reference.

Buzz

The language magusfiles are written in (the .buzz engine). See engines.

Sandbox

The restricted filesystem and environment a target runs in, so builds stay reproducible and side-effect-free. See sandbox.

CI

An ordinary magusfile-defined target you compose yourself with magus\needs - magus does not hardcode its stages. Magus.RunCI treats it specially only in that it strips the rw charm, it is the anchor magus affected ci keys off, and a selected scope with no project declaring it is a load error rather than a silent no-op. See targets.

Trace

OpenTelemetry's name for one whole magus invocation; every target it runs is a span beneath it. See telemetry.

Conventions

This page uses none of the site's convention markers. The full set is on the conventions page.