charmbracelet/crush · error

interpreter %q not found in PATH

Error message

interpreter %q not found in PATH

What it means

resolveInterpreter failed to locate the shebang interpreter. When the shebang names a bare interpreter (no path separators, e.g. `#!/usr/bin/env bash` resolved to `bash`), the resolver falls back to exec.LookPath; if that lookup fails (ENOENT), the interpreter name is wrapped in this error. It means neither the literal path nor PATH contains a usable binary.

Source

Thrown at internal/shell/dispatch.go:240

//
// The permissive fallback is what makes #!/bin/bash portable to Windows
// boxes where Git for Windows puts bash.exe on PATH but there is no
// /bin/bash on disk.
func resolveInterpreter(path string) (string, error) {
	_, statErr := os.Stat(path)
	if statErr == nil {
		return path, nil
	}
	if !errors.Is(statErr, fs.ErrNotExist) {
		return "", statErr
	}

	base := filepath.Base(path)
	if base == "" || base == path && !strings.ContainsAny(path, `/\`) {
		// Already a bare name — just do a PATH lookup.
		resolved, err := exec.LookPath(path)
		if err != nil {
			return "", fmt.Errorf("interpreter %q not found in PATH", path)
		}
		return resolved, nil
	}
	resolved, err := exec.LookPath(base)
	if err != nil {
		return "", fmt.Errorf("interpreter %q not found and %q not in PATH", path, base)
	}
	slog.Debug("Shebang interpreter not found; falling back to PATH",
		"requested", path, "resolved", resolved)
	return resolved, nil
}

// shebang captures the parsed `#!` line. interpreter is the program to
// invoke; args is the list of extra arguments to pass before the script
// path. The kernel's single-arg semantics (for literal paths and for env
// without `-S`) is encoded by returning a single-element args slice
// containing the un-tokenized remainder.
type shebang struct {

View on GitHub (pinned to 7944b8e522)

Solutions

  1. Install the interpreter named in the shebang (or a package providing it) so it appears on PATH.
  2. Rewrite the shebang to a literal path that exists on the target machine, e.g. #!/bin/sh instead of a missing interpreter.
  3. On Windows, install Git for Windows and ensure bash.exe is on PATH so the permissive fallback can resolve it.
  4. Verify PATH inside the execution environment (container, hook, CI job) — it may differ from your interactive shell PATH.

Example fix

// before
#!/usr/bin/env zsh
echo hi
// after
#!/bin/sh
echo hi
Defensive patterns

Strategy: validation

Validate before calling

if _, err := exec.LookPath("bash"); err != nil {
    // interpreter missing; install or fix shebang before running the script
}

Try / catch

if err != nil {
    var notFound bool
    if strings.Contains(err.Error(), "not found in PATH") {
        notFound = true
    }
    _ = notFound
}

Prevention

When it happens

Trigger: A script with a shebang naming an interpreter that (a) contains no '/' so it is treated as a bare name, or (b) whose literal path does not exist (os.Stat returns fs.ErrNotExist) and whose basename is not on PATH. Raised by dispatchShebang whenever exec.LookPath returns an error for the bare name.

Common situations: Scripts authored for macOS/Linux run on minimal Windows containers where bash/zsh are not installed; typos in the shebang interpreter name; CI images stripped of the expected runtime (e.g. no python3); NixOS-style setups where /usr/bin/env shims are absent.

Related errors


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