elastic/elasticsearch · error · IllegalStateException

unable to read from standard input; is standard input open a

Error message

unable to read from standard input; is standard input open and a tty attached?

What it means

Thrown by Terminal.read when the underlying reader returns null, meaning EOF was reached before any input was read. The Terminal class wraps System.in via a Console-like reader, and a null read indicates stdin is closed, redirected from /dev/null, or detached from a tty. The IllegalStateException is unrecoverable for interactive prompts (keystore password, confirmation) because there is no way to obtain the input the prompt needs.

Source

Thrown at libs/cli-terminal/src/main/java/org/elasticsearch/cli/terminal/Terminal.java:140

     * <p> Defaults to {@link Verbosity#NORMAL}.
     */
    public void setVerbosity(Verbosity verbosity) {
        this.currentVerbosity = verbosity;
    }

    /**
     * Return the current verbosity level of this terminal.
     */
    public Verbosity getVerbosity() {
        return currentVerbosity;
    }

    private char[] read(String prompt) {
        errWriter.print(prompt); // prompts should go to standard error to avoid mixing with list output
        errWriter.flush(); // flush to ensure it is seen
        final char[] line = readLineToCharArray(reader);
        if (line == null) {
            throw new IllegalStateException("unable to read from standard input; is standard input open and a tty attached?");
        }
        return line;
    }

    /** Reads clear text from the terminal input. See {@link Console#readLine()}. */
    public String readText(String prompt) {
        return new String(read(prompt));
    }

    /** Reads password text from the terminal input. See {@link Console#readPassword()}}. */
    public char[] readSecret(String prompt) {
        return read(prompt);
    }

    /** Returns a Reader which can be used to read directly from the terminal using standard input. */
    public final Reader getReader() {
        return reader;
    }

View on GitHub (pinned to db6a809a66)

Solutions

  1. Provide the input non-interactively via stdin: `printf 'secret\n' | bin/elasticsearch-keystore add-file ...`.
  2. Allocate a TTY when running remotely: `ssh -t` or `docker run -it`.
  3. Use the command's non-interactive flag (e.g. `--stdin` for keystore add) so it does not prompt.
  4. For daemons, ensure the startup environment has stdin attached or redirected from a controlled source.

Example fix

# before (no tty)
ssh es-host 'bin/elasticsearch-keystore add-file x.file'
# after
ssh -t es-host 'bin/elasticsearch-keystore add-file x.file'
# or feed stdin directly
ssh es-host 'bin/elasticsearch-keystore add --stdin -x setting < /path/to/value'
Defensive patterns

Strategy: validation

Validate before calling

if (System.console() == null && requiresInteractiveInput) {
    throw new IllegalStateException("No TTY attached; pass input via stdin or use --stdin flag.");
}

Type guard

static boolean hasInteractiveStdin() {
    return System.console() != null;
}

Try / catch

try {
    char[] secret = terminal.readSecret("Password: ");
} catch (IllegalStateException e) {
    if (e.getMessage().contains("standard input")) {
        // fall back to reading from a provided file/env var instead of prompting
    } else throw e;
}

Prevention

When it happens

Trigger: Running an interactive CLI command under cron, systemd without a TTY, `nohup`, or with stdin redirected from `/dev/null`. Piping a non-interactive stream into a command that expects a secret prompt. Running inside a container without `-it`.

Common situations: Automating `elasticsearch-keystore create` without supplying stdin. CI shells that close stdin by default. `ssh host command` (no PTY allocated) invoking an interactive prompt.

Related errors


AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12). Data as JSON: /api/errors/efbf4b3a92fe3f23. Report an issue: GitHub.