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

MGS6001: charm patch does not apply to the command

magus describe target <name>:<charm> was asked to preview the charm-applied command, but applying the charm's JSON Patch to the target's argv failed. The patch is well-formed (it passed the shape check every charm declaration goes through) yet does not fit this target's actual arguments, so the charm would change nothing here.

[MGS6001] target "lint" in project ".": charm(s) [rw] do not apply to spell "go"'s
command (json-patch: index 7 out of range for argv of length 4)
  see: .../MGS6001.md

Why

A charm is an RFC 6902 patch over a target's argument vector (see charms). Magus validates a charm's shape when the spell loads: the op is one of the six, the path is a /-rooted JSON Pointer, a move/copy carries a from. That check cannot know whether the pointer resolves, because it does not have the target's argv in hand.

The pointer is only resolved when the charm is applied to a concrete command. Two well-formed patches fail at that point:

  • An out-of-range index. {"op": "add", "path": "/7", ...} against a four-element argv has nowhere to land. This is what a hand-written positional patch drifts into when the base command changes and the counted index is not updated (the reason the charm constructors anchor by value instead).
  • A failing test op. {"op": "test", "path": "/1", "value": "run"} asserts the element is still where the author expected; when it is not, the patch is rejected on purpose.

Before this diagnostic, magus describe silently dropped the command: line for such a target: the preview rendered without the charm and without a word, so you could not tell a charm had failed to apply until a real run. Magus now surfaces it, because a charm that is dead on a target is exactly the kind of deterministic-but-invisible gap describe exists to close.

Resolution

Fix the charm declaration so its patch fits the target's argv:

  • Prefer a value anchor over a counted index. Replace a literal "/7" with a constructor that resolves the position at author time (charm\after(args, "run", [...])), so the pointer tracks the argv instead of a stale count. See the constructor reference.
  • Check the base command. Run magus describe target <name> with no charm to see the argv the charm must patch, then confirm the index or anchor the charm targets exists in it.
  • Relax or remove a stale test op. A test op guards a position; if the base argv legitimately changed, update the asserted value or drop the guard.

What this is not

  • Not a malformed patch. A patch with a bad op name or a non-rooted path is rejected earlier, at spell load, not here. MGS6001 is specifically a well-formed patch that does not apply to this target.
  • Not a runtime failure. describe executes nothing. This is a static preview diagnostic; the same mismatch would also fail a real run, which is why surfacing it early is worthwhile.

See also

MGS6001charmsjson-patchrfc-6902describeargvpreview
Last updated (353014be)
Earlier changes on this page (3)

Full history ↗ · Blame source ↗

Glossary

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.

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.

Charm

An execution modifier attached with : (lint:rw) that changes how a target runs, not which one; the built-in rw flips a check-only target to mutate in place, and ci always strips it. Charm 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.

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.

Conventions

Placeholders

Angle brackets mark a value you replace with your own; never type the brackets:

magus run <target>
magus completion <shell>    # e.g. bash, zsh, fish

<target>, <path>, <shell>, <name> and the like are stand-ins, not literal text.