charmbracelet/crush · error

unsupported env flag: %s

Error message

unsupported env flag: %s

What it means

parseEnvShebang rejects `env` shebangs that use any flag other than -S (split-string). The dispatcher implements env rewriting itself rather than forwarding to a real /usr/bin/env, and deliberately refuses unknown flags because forwarding them to a real env binary would be a portability footgun.

Source

Thrown at internal/shell/dispatch.go:337

// whitespace. Any other `env` flag is rejected — forwarding unknown flags
// to a /usr/bin/env on disk is a subtle portability footgun we don't want.
func parseEnvShebang(rest string) (*shebang, error) {
	if rest == "" {
		return nil, errors.New("env: missing program name")
	}

	useSplit := false
	if strings.HasPrefix(rest, "-") {
		var flag, after string
		if idx := strings.IndexAny(rest, " \t"); idx >= 0 {
			flag = rest[:idx]
			after = strings.TrimLeft(rest[idx+1:], " \t")
		} else {
			flag = rest
			after = ""
		}
		if flag != "-S" {
			return nil, fmt.Errorf("unsupported env flag: %s", flag)
		}
		useSplit = true
		rest = after
		if rest == "" {
			return nil, errors.New("env -S requires a program")
		}
	}

	if rest == "" {
		return nil, errors.New("env: missing program name")
	}

	var prog, remainder string
	if idx := strings.IndexAny(rest, " \t"); idx >= 0 {
		prog = rest[:idx]
		remainder = strings.TrimLeft(rest[idx+1:], " \t")
	} else {
		prog = rest

View on GitHub (pinned to 7944b8e522)

Solutions

  1. Replace the env flag with plain env form: `#!/usr/bin/env <interpreter>`.
  2. If you need a clean environment, unset variables in the script body instead of using `env -i`.
  3. Use `#!/usr/bin/env -S <interpreter> <args>` if the goal was argument splitting; only -S is supported.
  4. If the interpreter needs a custom PATH, export PATH at the top of the script rather than via env -P.

Example fix

// before
#!/usr/bin/env -i bash
set -e
// after
#!/usr/bin/env bash
set -e
Defensive patterns

Strategy: validation

Validate before calling

// reject env flags other than -S in shebangs before shipping
for _, line := range lines {
    if strings.HasPrefix(line, "#!") && strings.Contains(line, "env -") && !strings.Contains(line, "env -S ") {
        return fmt.Errorf("unsupported env flag in shebang: %s", line)
    }
}

Try / catch

var unsupported bool
if strings.HasPrefix(err.Error(), "unsupported env flag:") {
    unsupported = true
}

Prevention

When it happens

Trigger: A script's shebang is an env form whose first token after `env` starts with '-' but is not exactly "-S", e.g. `#!/usr/bin/env -i bash`, `#!/usr/bin/env -P /opt/bin python`, or `#!/usr/bin/env --split-string bash`.

Common situations: Portable scripts using `env -i` for a clean environment; BSD/macOS scripts using `env -P` to override PATH lookup; scripts using the long form `--split-string`; NixOS wrappers emitting extra env flags.

Related errors


AI-assisted analysis of charmbracelet/crush@7944b8e522 (2026-08-29). Data as JSON: /api/errors/6274d7dc76a2f6a5. Report an issue: GitHub.