nikivdev/code · error

no session specified (interactive selection requires a TTY)

Error message

no session specified (interactive selection requires a TTY)

What it means

The session open command supports interactive selection when no explicit session argument is given, but only when stdin is a TTY. If no session was specified and stdin is not a terminal (CI, piped input, background job), interactive selection is impossible, so the command bails.

Source

Thrown at src/ai.rs:13323

        }
    }

    let index = load_index()?;
    let sessions = read_sessions_for_project(provider)?;

    if sessions.is_empty() && session.is_none() {
        let provider_name = match provider {
            Provider::Claude => "Claude",
            Provider::Codex => "Codex",
            Provider::Cursor => "Cursor",
            Provider::All => "AI",
        };
        println!("No {} sessions found for this project.", provider_name);
        return Ok(());
    }

    if session.is_none() && !io::stdin().is_terminal() {
        bail!("no session specified (interactive selection requires a TTY)");
    }

    // Find the session ID and provider
    let (session_id, session_provider) = if let Some(ref query) = session {
        resolve_session_selection(query, &sessions, &index, provider)?
    } else {
        // Show fzf selection
        let mut entries: Vec<FzfSessionEntry> = Vec::new();

        for session in &sessions {
            if session.timestamp.is_none()
                && session.last_message_at.is_none()
                && session.last_message.is_none()
                && session.first_message.is_none()
                && session.error_summary.is_none()
            {
                continue;
            }

View on GitHub (pinned to a747e741ae)

Solutions

  1. Pass an explicit session ID/query argument so selection isn't needed
  2. Allocate a TTY (run in an interactive terminal, or `script -qc` / `ssh -t`)
  3. List sessions first (`f codex sessions`) and script the choice explicitly

Example fix

// before
CI_JOB=1 f codex open   # no TTY -> bail
// after
f codex open "$(f codex sessions --latest-id)"
Defensive patterns

Strategy: validation

Validate before calling

if session_arg.is_none() && !atty::is(atty::Stream::Stdin) {
    eprintln!("no session specified (interactive selection requires a TTY)");
    std::process::exit(2);
}

Type guard

fn needs_explicit_session(session: &Option<String>, stdin_tty: bool) -> bool {
    session.is_none() && !stdin_tty
}

Prevention

When it happens

Trigger: Running `f codex open` (or equivalent) with no session argument while stdin is redirected/piped — e.g. in CI pipelines, scripts, `cargo run < file`, or non-interactive shells.

Common situations: CI jobs invoking the CLI without a session ID; shell scripts piping into the command; running under a process manager or IDE terminal without TTY allocation.

Related errors


AI-assisted analysis of nikivdev/code@a747e741ae (2026-09-01). Data as JSON: /api/errors/e8222c5f836c7956. Report an issue: GitHub.