gleam-lang/gleam · critical
stdin read_line
Error message
stdin read_line
What it means
In the Hex OAuth device flow, Gleam prints a verification code and waits for the user to press Enter before opening the browser (compiler-cli/src/hex/auth.rs:340). It calls `std::io::stdin().read_line(&mut String::new()).expect("stdin read_line")`. Because the bytes are appended into a `String`, `read_line` returns Err (not EOF) when stdin delivers invalid UTF-8, or when stdin is a closed/bad file descriptor; the expect then aborts the login. A clean EOF (Ctrl-D, </dev/null) is Ok(0) and does NOT trigger this.
Source
Thrown at compiler-cli/src/hex/auth.rs:340
fn send_user_to_oauth_verification_url(device_authorisation: &hexpm::OAuthDeviceAuthorisation) {
// We make them press Enter to open the browser instead of going there immediately,
// to make sure they see the code before the browser window potentially hides the
// terminal window.
let uri = &device_authorisation.verification_uri;
println!(
"Your Hex verification code:
{code}
Verify this code matches what is shown in your browser.
Press Enter to open {uri}",
code = device_authorisation.user_code,
);
let _ = std::io::stdin()
.read_line(&mut String::new())
.expect("stdin read_line");
if opener::open_browser(uri).is_err() {
println!("\nFailed to open the browser, please navigate to {uri}");
}
}
#[derive(Debug, serde::Serialize, serde::Deserialize)]
struct StoredOAuthRepoCredentials {
#[serde(with = "http_serde::uri")]
api: http::Uri,
#[serde(with = "http_serde::uri")]
repository: http::Uri,
/// An encrypted refresh token.
refresh_token: String,
/// The hash of the token, so it can be revoked even if it cannot be encrypted.
refresh_token_hash: String,
}
#[derive(Debug, serde::Serialize, serde::Deserialize)]View on GitHub (pinned to 7e623aa83d)
Solutions
- Run the command interactively in a terminal and press Enter at the prompt
- For non-interactive use, pipe clean UTF-8 input: `echo | gleam hex authenticate` (a single newline is all it needs)
- Point stdin at /dev/null (`gleam hex authenticate < /dev/null`) instead of leaving a closed fd or binary pipe
- Fix CI wrappers that close fd 0 so stdin is a valid pipe or file
Example fix
# before: binary piped to stdin -> read_line InvalidData -> panic 'stdin read_line' cat data.bin | gleam hex authenticate # after: valid UTF-8 newline satisfies the prompt echo | gleam hex authenticate
Defensive patterns
Strategy: validation
Validate before calling
# non-interactive wrapper: give the Enter prompt a clean UTF-8 newline if [ -t 0 ]; then gleam hex authenticate else echo | gleam hex authenticate fi
Prevention
- Never pipe binary or non-UTF-8 data into commands that prompt on stdin
- Redirect stdin from /dev/null in cron/CI instead of leaving it closed or attached to random pipes
- Answer prompts with simple `echo`/here-string input in automation
When it happens
Trigger: Running `gleam hex authenticate` (or the OAuth prompt reached from `gleam publish`) with non-UTF-8 bytes piped to stdin (e.g. `gleam hex authenticate < data.bin`), or under a wrapper where fd 0 is closed or invalid (some CI steps, daemonized processes).
Common situations: Automation that pipes files into every command; CI jobs with closed stdin; a previous pipe stage emitting binary garbage; here-documents containing non-UTF-8 bytes used to 'answer' the prompt.
Related errors
- hostname
- Unable to start Tokio async runtime
- Unable to start Tokio async runtime
- Non Utf-8 Path
- Non-UTF8 path in hardlink_dir
AI-assisted analysis of gleam-lang/gleam@7e623aa83d (2026-08-17).
Data as JSON: /api/errors/68ec3f41ae84571b.
Report an issue: GitHub.