---
title: "MGS3026: queue hook is not a command"
description: magus queue refused a --gate, --regenerate or --facts value holding shell syntax, since the queue runs a hook as a command and its arguments with no shell.
tags: [MGS3026, merge queue, magus queue, hooks, shell]
---

# MGS3026: queue hook is not a command

`magus queue plan`, `validate` or `apply` read a hook flag whose value is not a
command and its arguments.

```text
[MGS3026] --gate "magus run ci | tee gate.log": | joins two commands, and a hook is
a command and its arguments with no shell to act on it; put the line in a script
and point --gate at it
```

## Why

The queue runs `--gate`, `--regenerate` and `--facts` directly, with the
change's projects (or the fact asked for) appended as arguments. No shell sits
between them, so a variable, a command substitution, a pipe, `;`, `&&`, a
redirection, a glob or a leading `NAME=value` would reach the program as
literal text, or not at all. The queue refuses the flag before anything runs
rather than run something other than what the line reads as.

Quotes and backslashes still group words: `--gate 'magus run "ci" --no-default-charms'`
is three words after `magus`.

## Resolution

Put the shell line in a script whose last command takes the appended arguments,
and point the flag at the script:

```sh
#!/bin/sh
set -eu
magus run ci --no-default-charms "$@" 2>&1 | tee gate.log
```

```sh
magus queue validate --gate ./tools/queue-gate.sh ...
```

For a tool cache, use `--scratch-env NAME=DIR` rather than an assignment
prefix; for magus's sandbox, its global flag (`magus --sandbox=required run
generate:rw`). See the [merge queue guide](../../../concepts/merge-queue.md#hooks-on-each-candidate).
