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
- Provide the input non-interactively via stdin: `printf 'secret\n' | bin/elasticsearch-keystore add-file ...`.
- Allocate a TTY when running remotely: `ssh -t` or `docker run -it`.
- Use the command's non-interactive flag (e.g. `--stdin` for keystore add) so it does not prompt.
- 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
- Detect `System.console() == null` before prompting and switch to non-interactive input.
- Prefer `--stdin` flags that read secrets from a pipe rather than a TTY.
- In CI/SSH, allocate a PTY (`ssh -t`, `docker run -it`) when prompting is unavoidable.
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
- Failed to parse value [{}] as only [true] or [false] are all
- 74
- USAGE
- Unknown secure settings source [${source}]
- CONFIG
AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12).
Data as JSON: /api/errors/efbf4b3a92fe3f23.
Report an issue: GitHub.