---
title: "MGS3021: preflight outside the closure"
description: A target named by --preflight is not one the invoked target reaches through ctx.needs in any selected project, so running it first would add work rather than reorder it. Exits 2.
tags: [MGS3021, preflight, ctx.needs, chain, closure, describe target, exit 2]
---

# MGS3021: preflight outside the closure

`--preflight` reorders work the invoked target already does: it runs part of that
target's `ctx.needs` closure first, everywhere, so a cheap failure stops the run before
the expensive part starts. A name outside that closure would add work instead, so magus
refuses the invocation before anything runs, and exits **2**, the misuse status.

```text
[MGS3021] --preflight unrelated is not in what ci runs in any selected project, so running it first would add work rather than reorder it (see `magus describe target ci`)
  app:ci chain: lint -> build -> test
  see: https://eli.gladman.cc/magus/reference/codes/sandbox/MGS3021/
```

Each listed line is a selected project, the invoked target, and its chain: the same
first hop `magus describe target <target>` prints. The closure is that chain followed
transitively, so a target `lint` needs counts for `ci` when `ci` needs `lint`.

Naming the invoked target itself is refused the same way: it is not a step before
itself.

A project whose invoked target does not reach the name runs no preflight for it; the
refusal fires only when no selected project reaches it. A preflight names a target
alone, with no charm: it runs under the invocation's charms, so it is keyed the way the
main run would key it.

## Resolution

- Name a target the invoked target composes. `magus describe target <target>` shows
  its chain.
- If the check should gate the invoked target, add it to that target's `ctx.needs`,
  then name it in `--preflight`.

## See also

- [MGS3020](MGS3020.md): a preflight target that ran and failed.
- [Targets](../../../concepts/targets.md#failing-fast-with---preflight): using
  --preflight before a CI fan-out.
