---
title: "MGS3020: preflight failed"
description: A target named by --preflight failed in at least one project, so magus stopped before the invoked target started anywhere. Exits 3.
tags: [MGS3020, preflight, ci, fail fast, drift, generate, exit 3]
---

# MGS3020: preflight failed

`magus run` and `magus affected` take `--preflight <target>[,<target>...]`. The named
targets run first, as a separate pass across every selected project, before the
invoked target starts anywhere. One of them failed, so nothing else ran and the
command exits **3**.

The first line names the target, the failing projects and the command to run next.
Each failure's own first line follows it:

```text
[MGS3020] preflight generate failed in docs, proto; fix with `magus run generate:rw docs`; reproduce with `magus run generate proto`
  docs:generate: docs: generate left declared output stale; re-run with the rw charm (generate:rw) and commit:
  proto:generate: generate failed in proto: buzz: uncaught error: ...
  see: https://eli.gladman.cc/magus/reference/codes/sandbox/MGS3020/
```

A project whose failure is drift (the target left declared output stale) gets the
rw form, `magus run <target>:rw <projects>`, because regenerating and committing is
the fix. Any other failure gets the plain form, which reproduces it.

## What stops, and when

The pass admits steps with a failure budget of one, the same mechanism
`max_failures: 1` uses. The first failure stops admission and cancels the preflight
steps still in flight; none of the invoked target is admitted afterwards. The per-target
lines above the error are each failing step's own report, with its captured output.

With `magus affected <target> --plan`, the pass runs across the planned projects before
the plan prints, and a failure prints no plan at all, so a workflow that fans shards out
from it starts none.

Exit 3 is kept apart from 1 so a CI script can tell the cheap check failing from the
fan-out failing.

## Resolution

1. Run the command the first line names. For drift, commit what it regenerated.
2. Re-run the original command. A green preflight pass is cached like any other run,
   so the second attempt pays only for what changed.

## See also

- [MGS3021](MGS3021.md): a --preflight target the invoked target never reaches.
- [Targets](../../../concepts/targets.md#failing-fast-with---preflight): using
  --preflight before a CI fan-out.
