{"record":{"id":"63755623a2261e4f","repo":"kovidgoyal/kitty","slug":"failed-to-open-controlling-terminal-with-error-w","errorCode":null,"errorMessage":"Failed to open controlling terminal with error: %w","messagePattern":"Failed to open controlling terminal with error: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kittens/icat/main.go","lineNumber":185,"sourceCode":"\terr = parse_z_index()\n\tif err != nil {\n\t\treturn 1, err\n\t}\n\terr = parse_background()\n\tif err != nil {\n\t\treturn 1, err\n\t}\n\terr = parse_mirror()\n\tif err != nil {\n\t\treturn 1, err\n\t}\n\tif opts.UseWindowSize == \"\" {\n\t\tif tty.IsTerminal(os.Stdout.Fd()) {\n\t\t\tscreen_size, err = tty.GetSize(int(os.Stdout.Fd()))\n\t\t} else {\n\t\t\tt, oerr := tty.OpenControllingTerm()\n\t\t\tif oerr != nil {\n\t\t\t\treturn 1, fmt.Errorf(\"Failed to open controlling terminal with error: %w\", oerr)\n\t\t\t}\n\t\t\tscreen_size, err = t.GetSize()\n\t\t}\n\t\tif err != nil {\n\t\t\treturn 1, fmt.Errorf(\"Failed to query terminal using TIOCGWINSZ with error: %w\", err)\n\t\t}\n\t} else {\n\t\tparts := strings.SplitN(opts.UseWindowSize, \",\", 4)\n\t\tif len(parts) != 4 {\n\t\t\treturn 1, fmt.Errorf(\"Invalid size specification: %s\", opts.UseWindowSize)\n\t\t}\n\t\tscreen_size = &unix.Winsize{}\n\t\tvar t uint64\n\t\tif t, err = strconv.ParseUint(parts[0], 10, 16); err != nil || t < 1 {\n\t\t\treturn 1, fmt.Errorf(\"Invalid size specification: %s with error: %w\", opts.UseWindowSize, err)\n\t\t}\n\t\tscreen_size.Col = uint16(t)\n\t\tif t, err = strconv.ParseUint(parts[1], 10, 16); err != nil || t < 1 {","sourceCodeStart":167,"sourceCodeEnd":203,"githubUrl":"https://github.com/kovidgoyal/kitty/blob/6d5d0c440603ad9bdf6dcd599f73f6dde21acb44/kittens/icat/main.go#L167-L203","documentation":"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).","triggerScenarios":"Running icat with output piped/redirected in a process with no controlling terminal (daemon, CI job, detached process) or where /dev/tty is inaccessible.","commonSituations":"Using icat in scripts/CI, inside certain sandboxes or containers without a TTY, or with unusual fd setups.","solutions":["Run icat with stdout attached to a real terminal","Alternatively pass an explicit size via --use-window-size to avoid TTY probing","Ensure the process has a controlling terminal (not fully detached)"],"exampleFix":"# before (no tty)\nkitty +kitten icat img.png > out.txt\n# after\nkitty +kitten icat --use-window-size 80,24,7,10 img.png > out.txt","handlingStrategy":"fallback","validationCode":"if !tty.IsTerminal(os.Stdout.Fd()) && opts.UseWindowSize == \"\" { opts.UseWindowSize = \"80,24,7,14\" }","typeGuard":null,"tryCatchPattern":"On 'Failed to open controlling terminal', degrade gracefully: use default dimensions or abort with guidance to run in a terminal.","preventionTips":["Pass --use-window-size in scripts/CI","Ensure icat runs attached to a terminal or provide explicit size"],"tags":["kitty","icat","tty","environment"],"backgroundTag":"no-controlling-terminal","analyzedSha":"6d5d0c440603ad9bdf6dcd599f73f6dde21acb44","analyzedAt":"2026-08-27T14:20:20.142Z","schemaVersion":2},"datasetVersion":"2026-08-27T19:17:21.184Z"}