python/cpython · error · RuntimeError

insufficient terminal (vertical)

Error message

insufficient terminal (vertical)

What it means

RuntimeError from UnixConsole.__setup_movement (Lib/_pyrepl/unix_console.py). Vertical cursor movement requires either the parameterized cuu+cud pair or the single-step cuu1+cud1 pair. A terminal entry with none of the four capabilities raises 'insufficient terminal (vertical)' during console init; it typically appears together with (or right after) the horizontal variant on the same crippled TERM entry.

Source

Thrown at Lib/_pyrepl/unix_console.py:760

    def __setup_movement(self):
        """
        Set up the movement functions based on the terminal capabilities.
        """
        if 0 and self._hpa:  # hpa don't work in windows telnet :-(
            self.__move_x = self.__move_x_hpa
        elif self._cub and self._cuf:
            self.__move_x = self.__move_x_cub_cuf
        elif self._cub1 and self._cuf1:
            self.__move_x = self.__move_x_cub1_cuf1
        else:
            raise RuntimeError("insufficient terminal (horizontal)")

        if self._cuu and self._cud:
            self.__move_y = self.__move_y_cuu_cud
        elif self._cuu1 and self._cud1:
            self.__move_y = self.__move_y_cuu1_cud1
        else:
            raise RuntimeError("insufficient terminal (vertical)")

        if self._dch1:
            self.dch1 = self._dch1
        elif self._dch:
            self.dch1 = terminfo.tparm(self._dch, 1)
        else:
            self.dch1 = None

        if self._ich1:
            self.ich1 = self._ich1
        elif self._ich:
            self.ich1 = terminfo.tparm(self._ich, 1)
        else:
            self.ich1 = None

        self.__move = self.__move_short

    @staticmethod

View on GitHub (pinned to bc6749cc3b)

Solutions

  1. Set TERM=xterm or another fully capable entry before starting Python.
  2. Install/repair terminfo databases (ncurses-base/terminfo packages; infocmp/tic to copy entries).
  3. Keep the REPL out of non-tty code paths: guard interactive entry with sys.stdin.isatty().

Example fix

# before
# TERM=dumb python -i   -> RuntimeError: insufficient terminal (vertical)

# after
# TERM=xterm python -i
Defensive patterns

Strategy: fallback

Validate before calling

import os

def vertical_movement_capable():
    # crude proxy: full terminfo entries for common TERMs define cuu/cud
    return os.environ.get('TERM', '') not in {'', 'dumb', 'unknown'}

Prevention

When it happens

Trigger: Same class as the horizontal failure: TERM=dumb/unknown or a terminfo entry lacking cursor-up/down strings when the pyrepl REPL initializes its movement functions in __setup_movement.

Common situations: Headless containers, cron contexts, or embedded systems whose terminfo db is stripped; TERMCAP-based legacy environments; TERM forwarded over SSH to a host that lacks that entry (falls back to a minimal one).

Related errors


AI-assisted analysis of python/cpython@bc6749cc3b (2026-08-14). Data as JSON: /api/errors/7929c91e906538f3. Report an issue: GitHub.