charmbracelet/glow · error
unable to run command: %w
Error message
unable to run command: %w
What it means
After editor.Cmd successfully builds the command, glow wires os.Stdin/Stdout/Stderr to it and calls c.Run(). This error wraps any failure from that execution: the process could not be spawned, or it exited with a non-zero status. The config file path was already validated (ensureConfigFile ran first), so this is purely about the editor process.
Source
Thrown at config_cmd.go:48
Hidden: false,
Short: "Edit the glow config file",
Long: paragraph(fmt.Sprintf("\n%s the glow config file. We’ll use EDITOR to determine which editor to use. If the config file doesn't exist, it will be created.", keyword("Edit"))),
Example: paragraph("glow config\nglow config --config path/to/config.yml"),
Args: cobra.NoArgs,
RunE: func(*cobra.Command, []string) error {
if err := ensureConfigFile(); err != nil {
return err
}
c, err := editor.Cmd("Glow", configFile)
if err != nil {
return fmt.Errorf("unable to set config file: %w", err)
}
c.Stdin = os.Stdin
c.Stdout = os.Stdout
c.Stderr = os.Stderr
if err := c.Run(); err != nil {
return fmt.Errorf("unable to run command: %w", err)
}
fmt.Println("Wrote config file to:", configFile)
return nil
},
}
func ensureConfigFile() error {
if configFile == "" {
configFile = viper.GetViper().ConfigFileUsed()
if err := os.MkdirAll(filepath.Dir(configFile), 0o755); err != nil { //nolint:gosec
return fmt.Errorf("could not write configuration file: %w", err)
}
}
if ext := path.Ext(configFile); ext != ".yaml" && ext != ".yml" {
return fmt.Errorf("'%s' is not a supported configuration type: use '%s' or '%s'", ext, ".yaml", ".yml")
}View on GitHub (pinned to e3970c813d)
Solutions
- Confirm the exact editor command works standalone with a file argument
- Use a terminal editor (vim, nano) or add a wait flag: EDITOR="code --wait"
- If the editor aborted, fix the underlying cause it printed to stderr and rerun glow config
Example fix
# before $ EDITOR=code glow config # exits/renders nothing useful # after $ EDITOR="code --wait" glow config # or $ EDITOR=vim glow config
Defensive patterns
Strategy: try-catch
Validate before calling
// smoke-test the exact invocation glow will use
c := exec.Command(editorBin, "/tmp/probe.yml")
c.Stdin, c.Stdout, c.Stderr = os.Stdin, os.Stdout, os.Stderr
if err := c.Run(); err != nil {
log.Fatalf("editor smoke test failed: %v", err)
} Try / catch
if err := c.Run(); err != nil {
var exitErr *exec.ExitError
if errors.As(err, &exitErr) {
// editor ran but exited non-zero (e.g. vim :cq) — ask the user, keep the file
return fmt.Errorf("editor exited with status %d; rerun 'glow config' when ready", exitErr.ExitCode())
}
// spawn failure (missing binary, permissions, no TTY)
return fmt.Errorf("unable to run command: %w", err)
} Prevention
- Use a blocking terminal editor (vim/nano) or add a wait flag for GUIs: EDITOR='code --wait'
- Run glow config from a real TTY so the editor can take over stdin/stdout
- Distinguish ExitError (user aborted) from spawn errors — only the latter indicates a broken EDITOR value
When it happens
Trigger: EDITOR points to a binary that disappeared between lookup and exec (or lookup returned it despite PATH issues); the editor exits non-zero — e.g. quitting vim with :cq; GUI editors like VS Code launched as EDITOR=code without --wait exit immediately or misbehave without a TTY; exec permission denied on the editor binary.
Common situations: EDITOR="code" or EDITOR="subl" without a wait flag; scripts running glow config where stdout is not a terminal; editors that abort when the file is a symlink into a read-only path.
Related errors
- unable to set config file: %w
- unable to run command: %w
- cannot use both pager and tui
- could not write configuration file: %w
- '%s' is not a supported configuration type: use '%s' or '%s'
AI-assisted analysis of charmbracelet/glow@e3970c813d (2026-08-15).
Data as JSON: /api/errors/d694f59955d66b47.
Report an issue: GitHub.