{"record":{"id":"68ec3f41ae84571b","repo":"gleam-lang/gleam","slug":"stdin-read-line","errorCode":null,"errorMessage":"stdin read_line","messagePattern":"stdin read_line","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"compiler-cli/src/hex/auth.rs","lineNumber":340,"sourceCode":"fn send_user_to_oauth_verification_url(device_authorisation: &hexpm::OAuthDeviceAuthorisation) {\n    // We make them press Enter to open the browser instead of going there immediately,\n    // to make sure they see the code before the browser window potentially hides the\n    // terminal window.\n    let uri = &device_authorisation.verification_uri;\n    println!(\n        \"Your Hex verification code:\n\n    {code}\n\nVerify this code matches what is shown in your browser.\n\nPress Enter to open {uri}\",\n        code = device_authorisation.user_code,\n    );\n\n    let _ = std::io::stdin()\n        .read_line(&mut String::new())\n        .expect(\"stdin read_line\");\n    if opener::open_browser(uri).is_err() {\n        println!(\"\\nFailed to open the browser, please navigate to {uri}\");\n    }\n}\n\n#[derive(Debug, serde::Serialize, serde::Deserialize)]\nstruct StoredOAuthRepoCredentials {\n    #[serde(with = \"http_serde::uri\")]\n    api: http::Uri,\n    #[serde(with = \"http_serde::uri\")]\n    repository: http::Uri,\n    /// An encrypted refresh token.\n    refresh_token: String,\n    /// The hash of the token, so it can be revoked even if it cannot be encrypted.\n    refresh_token_hash: String,\n}\n\n#[derive(Debug, serde::Serialize, serde::Deserialize)]","sourceCodeStart":322,"sourceCodeEnd":358,"githubUrl":"https://github.com/gleam-lang/gleam/blob/7e623aa83da3776faee50ca4ab9a6c40124acd95/compiler-cli/src/hex/auth.rs#L322-L358","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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"],"exampleFix":"# before: binary piped to stdin -> read_line InvalidData -> panic 'stdin read_line'\ncat data.bin | gleam hex authenticate\n\n# after: valid UTF-8 newline satisfies the prompt\necho | gleam hex authenticate","handlingStrategy":"validation","validationCode":"# non-interactive wrapper: give the Enter prompt a clean UTF-8 newline\nif [ -t 0 ]; then\n  gleam hex authenticate\nelse\n  echo | gleam hex authenticate\nfi","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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"],"tags":["gleam","hex","oauth","stdin","authentication","utf-8"],"backgroundTag":"stdin-read-failed","analyzedSha":"7e623aa83da3776faee50ca4ab9a6c40124acd95","analyzedAt":"2026-08-17T00:07:02.091Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}