kovidgoyal/kitty · error

Failed to open controlling terminal with error: %w

Error message

Failed to open controlling terminal with error: %w

What it means

When stdout is not a TTY, icat opens the controlling terminal (/dev/tty) to query screen size; if that open fails, this error wraps the cause (e.g. permission denied or no controlling terminal).

Source

Thrown at kittens/icat/main.go:185

	err = parse_z_index()
	if err != nil {
		return 1, err
	}
	err = parse_background()
	if err != nil {
		return 1, err
	}
	err = parse_mirror()
	if err != nil {
		return 1, err
	}
	if opts.UseWindowSize == "" {
		if tty.IsTerminal(os.Stdout.Fd()) {
			screen_size, err = tty.GetSize(int(os.Stdout.Fd()))
		} else {
			t, oerr := tty.OpenControllingTerm()
			if oerr != nil {
				return 1, fmt.Errorf("Failed to open controlling terminal with error: %w", oerr)
			}
			screen_size, err = t.GetSize()
		}
		if err != nil {
			return 1, fmt.Errorf("Failed to query terminal using TIOCGWINSZ with error: %w", err)
		}
	} else {
		parts := strings.SplitN(opts.UseWindowSize, ",", 4)
		if len(parts) != 4 {
			return 1, fmt.Errorf("Invalid size specification: %s", opts.UseWindowSize)
		}
		screen_size = &unix.Winsize{}
		var t uint64
		if t, err = strconv.ParseUint(parts[0], 10, 16); err != nil || t < 1 {
			return 1, fmt.Errorf("Invalid size specification: %s with error: %w", opts.UseWindowSize, err)
		}
		screen_size.Col = uint16(t)
		if t, err = strconv.ParseUint(parts[1], 10, 16); err != nil || t < 1 {

View on GitHub (pinned to 6d5d0c4406)

Solutions

  1. Run icat with stdout attached to a real terminal
  2. Alternatively pass an explicit size via --use-window-size to avoid TTY probing
  3. Ensure the process has a controlling terminal (not fully detached)

Example fix

# before (no tty)
kitty +kitten icat img.png > out.txt
# after
kitty +kitten icat --use-window-size 80,24,7,10 img.png > out.txt
Defensive patterns

Strategy: fallback

Validate before calling

if !tty.IsTerminal(os.Stdout.Fd()) && opts.UseWindowSize == "" { opts.UseWindowSize = "80,24,7,14" }

Try / catch

On 'Failed to open controlling terminal', degrade gracefully: use default dimensions or abort with guidance to run in a terminal.

Prevention

When it happens

Trigger: Running icat with output piped/redirected in a process with no controlling terminal (daemon, CI job, detached process) or where /dev/tty is inaccessible.

Common situations: Using icat in scripts/CI, inside certain sandboxes or containers without a TTY, or with unusual fd setups.

Related errors


AI-assisted analysis of kovidgoyal/kitty@6d5d0c4406 (2026-08-27). Data as JSON: /api/errors/63755623a2261e4f. Report an issue: GitHub.