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

MGS1021: workspace requires a newer magus

The workspace declares the oldest magus that can run it, and the running binary is older than that. The check runs before any magusfile is evaluated, so nothing has been loaded yet.

[MGS1021] this workspace requires magus >= 0.4.0 and this build is v0.3.0.
Upgrade the binary (`magus self update`), or if this is CI, raise the pinned
version in your magus setup step. The workspace declares the floor in magus.yaml
(required_version).
  see: .../MGS1021.md

Why

magus adds features additively, so a magusfile that worked keeps working on every later release (see compatibility). The reverse is not promised: a magusfile using a host module or a magus\project key added last month cannot run on a binary built before it.

Without a declared floor, that situation surfaces from wherever the magusfile first touched the missing thing:

import "xml": module not found

which reads like a typo, not like an out-of-date tool. It sends people looking at their magusfile instead of their magus.

The floor has to be declared rather than derived, and the reason is worth being explicit about: the binary reporting the error is the old one. It cannot look up which release introduced xml, because it has never heard of that release. No table shipped in a newer magus can help, since the newer magus is not the one running. A declared minimum is the only claim an old binary can evaluate against a future it does not know about. Terraform's required_version, Go's go directive, and npm's engines all exist for exactly this.

Resolution

Two fixes, and which one you want depends on where you hit it.

Locally, upgrade the binary:

magus self update

In CI, raise the pinned version in your setup step, since CI deliberately runs a pinned, checksum-verified release rather than whatever is newest:

- uses: egladman/magus/.github/actions/setup-magus@main
  with:
    version: v0.4.0

Or lower the floor, if it was raised by mistake. The floor lives in magus.yaml:

required_version: ">= 0.4.0"

The value is a semver constraint. ">= 0.4.0" is the usual form; the key may be omitted entirely to declare no floor. A constraint magus cannot parse is reported under this same code rather than passing silently, so a typo cannot quietly read as "no floor declared".

A floor should name a RELEASED version. A build between releases describes itself from the last tag: a tree 42 commits past v0.3.0 reports v0.3.0-42-gabc and compares as 0.3.0, so a floor set to a version that has not shipped yet rejects builds from source, including of the commit that raised the floor.

A binary built from this checkout

MGS1021 also fires when a binary built from the checkout it runs in predates that checkout's sources, typically after a pull or a merge: the magusfile names something the binary has never heard of. That binary cannot rebuild itself, since every command it runs loads the same tree, so the message names a relink instead:

go build -o magus ./cmd/magus
./magus run go-build .

The bootstrap does the same in one command, and the guard allows it, alone on its line, over a ./magus that cannot load the tree. There is no need to move the old binary aside first:

GOEXPERIMENT=jsonv2 go run -trimpath ./cmd/magus run go-build --no-cache .

If the link fails with undefined: in generated code, the committed generated files are behind the sources because a merge kept one side of them. Restoring either side's copy keeps the mismatch. Regenerate them with what the *_generate targets run, in this order, then link again:

go generate ./cmd/magus-utils
go generate ./internal/spell/...
go run ./cmd/magus-utils jobschema -out internal/job/gen
go generate ./internal/langservice
go generate ./std/...
go generate ./internal/handler/mcp

In magus's own repository the agent guard allows exactly these commands and the bootstrap, each alone on its line, while the workspace fails with MGS1021, and refuses them again once it loads. See the raw-tool rule.

What this is not

  • Not a compatibility break. Nothing that worked has stopped working. This is the absence of forward compatibility, which magus does not promise and neither does any comparable tool.
  • Not a floor check against a dev build. An unstamped local build reports its version as unknown and is exempt from the floor: it is usually newer than any release, and blocking local development against a floor the working tree just raised would be backwards. A dev build that predates its checkout still gets MGS1021 the other way, above.
  • Not raised for a library caller. magus.Open without magus.WithVersion supplies no version, so there is nothing to compare and the check passes.

See also

  • compatibility: what magus promises across versions, and where the floor fits.
  • magus version: the running build's version.
  • magus doctor: reports a floor lower than what the workspace requires.
MGS1021magusfilemagus.yamlrequired_versionversionupgradecicompatibility
Last updated (89139ea5)
Earlier changes on this page (5)

Full history ↗ · Blame source ↗

Glossary

Workspace

The magus root directory that owns a set of projects and shared config; the unit magus operates over. Workspace in full.

Project

A directory magus recognizes as a unit of work (it has a magusfile); the unit of caching, scheduling, and dependency tracking. Project in full.

Magusfile

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

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. Target in full.

Op

A single tool-native command a target composes (long form: operation); the middle of the work hierarchy (Spell to Op to Target). Op in full.

Spell

A language/runtime adapter (e.g. go, md) that maps generic targets onto a toolchain's real commands. Spell in full.

Ward

A coded diagnostic that inspects a resolved op and nudges or blocks an anti-pattern before it runs. Ward in full.

Module

A magus stdlib namespace a magusfile imports for host capabilities: filesystem, exec, vcs, and more. Module in full.

Engine

The interpreter a magusfile runs on; magus embeds the Buzz engine. Engine in full.

Cache

The content-addressed store magus consults before running a target, so unchanged work is skipped. Cache in full.

Service

A long-running or shared process magus manages across runs, distinct from a one-shot target. Service in full.

CI

An ordinary target you compose yourself with ctx.needs; magus does not hardcode its stages. It is the anchor magus affected ci keys off, and ci strips the rw charm. CI in full.

Agent

A model working through an agent host such as Claude Code, Codex, Cursor or OpenCode. magus treats an agent as one more caller of its CLI, MCP tools and console, held to the same checks as a person. Agent in full.

Tool

An action a model can call through its host: a name, a description, a typed input and a result. magus serves its tools over MCP, each a read of the workspace model or a run of the CLI it already has. Tool in full.

Job

The unit of delegated work, and one row of the job store: what an orchestrating agent handed out, with its goal, the checkpoint it was cut against, the paths it may write or must not touch, and the one check it runs. A job's holder is either a session, for work an orchestrator handed out, or the daemon, for its own maintenance. The store records; the agent guard is what reads those facts back when grading a write. Job in full.

Run

One target executing under one magus invocation, such as magus run test web or magus affected ci. A run keeps its captured output behind an output reference. Every magus run is a run whether or not any job asked for it; see Job for how the two relate. Run in full.

Lease

The grant a holder takes on a job: the write and read paths that job declared, enforced in the checkout that took it with magus job exec. A job is the piece of work; a lease is permission over it. Lease in full.

Conventions

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