wezterm/wezterm · error

SetConsoleCursorPosition(x={}, y={}) failed: {}

Error message

SetConsoleCursorPosition(x={}, y={}) failed: {}

What it means

OutputHandle::set_cursor_position calls SetConsoleCursorPosition with COORD { X: x, Y: y } to move the cursor in the console screen buffer. It bails (including the coordinates in the message) when the call fails, which Windows signals when the requested coordinates are outside the screen buffer, or the handle is not a valid console output handle.

Source

Thrown at termwiz/src/terminal/windows.rs:311

        }
        Ok(wrote)
    }

    fn set_attr(&mut self, attr: u16) -> Result<()> {
        if unsafe { SetConsoleTextAttribute(self.handle.as_raw_handle(), attr) } == 0 {
            bail!(
                "SetConsoleTextAttribute failed: {}",
                IoError::last_os_error()
            );
        }
        Ok(())
    }

    fn set_cursor_position(&mut self, x: i16, y: i16) -> Result<()> {
        if unsafe { SetConsoleCursorPosition(self.handle.as_raw_handle(), COORD { X: x, Y: y }) }
            == 0
        {
            bail!(
                "SetConsoleCursorPosition(x={}, y={}) failed: {}",
                x,
                y,
                IoError::last_os_error()
            );
        }
        Ok(())
    }

    fn get_buffer_contents(&mut self) -> Result<Vec<CHAR_INFO>> {
        let info = self.get_buffer_info()?;

        let cols = info.dwSize.X as usize;
        let rows = 1 + info.srWindow.Bottom as usize - info.srWindow.Top as usize;

        let mut res = vec![
            CHAR_INFO {
                Attributes: 0,

View on GitHub (pinned to b99b1ca2cc)

Solutions

  1. Clamp x and y to the current buffer bounds from GetConsoleScreenBufferInfo before moving the cursor
  2. Recompute the full layout after every resize event and discard cached positions
  3. Treat a cursor-position failure as a repaint trigger, not a fatal error
  4. Validate that x >= 0, y >= 0 and fit in i16 before the call

Example fix

// before
out.set_cursor_position(x, y)?; // coordinates outside the screen buffer
// after: clamp to the current buffer bounds first
let info = out.get_buffer_info()?;
let x = x.clamp(0, info.size.x - 1);
let y = y.clamp(0, info.size.y - 1);
out.set_cursor_position(x, y)?;
Defensive patterns

Strategy: validation

Validate before calling

// clamp cursor coordinates to the current console buffer
let info = out.get_buffer_info()?;
let x = x.clamp(0, info.size.x - 1);
let y = y.clamp(0, info.size.y - 1);
out.set_cursor_position(x, y)?;

Try / catch

match out.set_cursor_position(x, y) {
    Ok(()) => (),
    Err(_) => request_full_repaint(), // stale coordinates after a resize
}

Prevention

When it happens

Trigger: Moving the cursor to a position beyond the current buffer dimensions: rendering with stale rows/cols right after the console shrank, computing positions from the viewport while the buffer is smaller, or passing negative coordinates that wrapped into invalid i16 values.

Common situations: Resize races where the layout is bigger than the new buffer; alternate approaches that assume the buffer is at least as large as the window; rapid manual window resizing; coordinate arithmetic that goes negative after shrinking.

Related errors


AI-assisted analysis of wezterm/wezterm@b99b1ca2cc (2026-09-05). Data as JSON: /api/errors/1213b5ea58923e05. Report an issue: GitHub.