denisidoro/navi · error

Not enough data

Error message

Not enough data

What it means

This panic comes from an `.expect("Not enough data")` on an iterator item in `width_with_shell_out` (src/common/terminal.rs:31). The function shells out to `stty size`, which prints '<rows> <cols>' on stdout; the code skips the first whitespace-separated token and expects a second token (the column count). If `stty` exits 0 but prints fewer than two tokens (or nothing), the iterator is exhausted and the expect panics. It is a hard panic, not a Result error, though the caller `width()` would have fallen back to 80 columns if it were propagated as an Err.

Source

Thrown at src/common/terminal.rs:31

            .arg("size")
            .stderr(Stdio::inherit())
            .output()?
    } else {
        Command::new("stty")
            .arg("size")
            .arg("-F")
            .arg("/dev/stderr")
            .stderr(Stdio::inherit())
            .output()?
    };

    if let Some(0) = output.status.code() {
        let stdout = String::from_utf8(output.stdout).expect("Invalid utf8 output from stty");
        let mut data = stdout.split_whitespace();
        data.next();
        return data
            .next()
            .expect("Not enough data")
            .parse::<u16>()
            .map_err(|_| anyhow!("Invalid width"));
    }

    Err(anyhow!("Invalid status code"))
}

pub fn width() -> u16 {
    if let Ok((w, _)) = terminal::size() {
        w
    } else {
        width_with_shell_out().unwrap_or(FALLBACK_WIDTH)
    }
}

#[cfg(test)]
mod tests {
    use super::*;

View on GitHub (pinned to f7330b9ad5)

Solutions

  1. Ensure the process runs with a real TTY on stderr (allocate a PTY, e.g. `ssh -t`, `script -qec`, or a Docker `-t` flag) so both crossterm and stty can report a size
  2. Verify `stty -F /dev/stderr size` (or `stty -f /dev/stderr size` on macOS) prints two numbers in your environment; fix or remove broken stty shims from PATH
  3. Upgrade the library / patch `width_with_shell_out` to check `data.next()` and return `Err(anyhow!("Not enough data"))` instead of panicking, so the existing FALLBACK_WIDTH=80 path applies
  4. As a workaround, force a known terminal size in CI (e.g. `stty cols 80 rows 24` or `COLUMNS=80`) before invoking

Example fix

// before
return data
    .next()
    .expect("Not enough data")
    .parse::<u16>()
    .map_err(|_| anyhow!("Invalid width"));
// after
return data
    .next()
    .ok_or_else(|| anyhow!("Not enough data"))?
    .parse::<u16>()
    .map_err(|_| anyhow!("Invalid width"));
Defensive patterns

Strategy: fallback

Validate before calling

// Run before relying on the shell-out path:
use std::process::Command;
fn stty_output_ok() -> bool {
    let out = Command::new("stty").arg("size").arg("-F").arg("/dev/stderr")
        .output().ok();
    match out {
        Some(o) if o.status.code() == Some(0) => {
            let s = String::from_utf8_lossy(&o.stdout);
            s.split_whitespace().count() >= 2
                && s.split_whitespace().nth(1).unwrap().parse::<u16>().is_ok()
        }
        _ => false,
    }
}

Type guard

fn valid_stty_size(stdout: &str) -> Option<u16> {
    let mut it = stdout.split_whitespace();
    it.next()?; // rows
    it.next()?.parse::<u16>().ok() // columns
}

Try / catch

// In Rust, prefer not panicking: change the expect to Result and rely on
// width()'s existing fallback (this library already falls back to 80):
match std::panic::catch_unwind(width_with_shell_out) {
    Ok(w) => w,
    Err(_) => 80, // FALLBACK_WIDTH
}

Prevention

When it happens

Trigger: `stty` is executed with exit code 0 but its stdout does not contain two whitespace-separated fields — e.g. stdout is empty, or contains only a row count — while the crossterm `terminal::size()` path has already failed (no real TTY). This can happen with unusual/patched stty builds, locale wrappers that emit extra warnings (only if they consume stdout), stubbed stty binaries in CI containers, or pseudo-terminal setups where stty reports success but no size.

Common situations: Running inside Docker/CI where stderr is redirected to a non-tty and an stty shim returns 0 with empty output; environments with a fake or busybox `stty` that behaves differently from GNU/coreutils stty; terminal multiplexers or wrappers that break crossterm's ioctl and then also break the stty fallback; SSH sessions with a broken PTY allocation.

Related errors


AI-assisted analysis of denisidoro/navi@f7330b9ad5 (2026-09-03). Data as JSON: /api/errors/286bf161c3820d60. Report an issue: GitHub.