---
title: "MGS1021: workspace requires a newer magus"
description: Fires when magus.yaml declares a required_version floor the running binary does not satisfy. Upgrade the binary, or raise the pinned version in CI.
tags:
  [MGS1021, magusfile, magus.yaml, required_version, version, upgrade, ci, compatibility]
---

# 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.

```text
[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](../../../concepts/compatibility.md)). 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:

```text
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:

```bash
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:

```yaml
- 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`:

```yaml title="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.

## 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 raised against a dev build.** An unstamped local build reports its version
  as `unknown` and is exempt: it is usually newer than any release, and blocking
  local development against a floor the working tree just raised would be
  backwards.
- **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](../../../concepts/compatibility.md): 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 actually requires.
