coding-horror/basic-computer-games · error

something went wrong getting user guess

Error message

something went wrong getting user guess

What it means

This panic is triggered by `.expect("something went wrong getting user guess")` on `get_string_from_user_input()` in the refactored Mastermind lib (line 126). Unlike the original Mastermind, `get_string_from_user_input` *properly* returns `Result<String, Box<dyn Error>>` with the underlying I/O error embedded (`"ERROR: CANNOT READ INPUT!: {err}"`). The caller then defeats this design by calling `.expect()`, converting a recoverable `Err` back into a panic.

Source

Thrown at 60_Mastermind/rust/Mastermind_refactored_for_conventions/src/lib.rs:126

/// run a round with computer as code-maker
/// returns the number of turns it takes the human to guess the secret code
fn play_round_computer_codemaker(config: &Config) -> Option<usize> {
    //DATA
    let mut rng = thread_rng();
    let mut guesses: Vec<Code> = Vec::new();
    let secret: Code;

    //generate secret
    secret = Code::new_from_int(rng.gen_range(0..config.num_colors.pow(config.num_positions.try_into().unwrap())), config);

    //round loop
    for human_moves in 1..=config.num_guesses {
        //get guess from user input
        //input loop
        let mut guess = loop {
            //get input
            let user_input = get_string_from_user_input(format!("\nMOVE # {} GUESS: ", human_moves).as_str()).expect("something went wrong getting user guess");

            //parse input
            if user_input.trim().eq_ignore_ascii_case("board") { //print the board state
                print_board(&guesses);
                continue; //run input loop again
            } else if user_input.trim().eq_ignore_ascii_case("quit") { //quit the game
                println!("QUITTER!  MY COMBINATION WAS: {}\nGOOD BYE", secret.as_human_readible_chars());
                return None; //exit the game
            } else {
                //parse input for a code
                match Code::new_from_string(&user_input, &config) {
                    Ok(code) => {
                        //ensure code is correct length
                        if code.code.len() != config.num_positions { // if not
                            println!("BAD NUMBER OF POSITIONS.");
                            continue; //run loop again
                        }
                        else {break code;}//break with the code

View on GitHub (pinned to 5301155192)

Solutions

  1. Propagate the error up: change `play_round_human_codebreaker` to return `Result<Option<usize>, Box<dyn Error>>` and use `?` instead of `.expect`.
  2. Match on the `Result`, printing the embedded error message and continuing the loop or returning `None` to gracefully exit.
  3. Refactor the call sites to match the function's `Result`-returning contract that was already implemented.

Example fix

// before
let user_input = get_string_from_user_input(
    format!("\nMOVE # {} GUESS: ", human_moves).as_str())
    .expect("something went wrong getting user guess");

// after
let user_input = match get_string_from_user_input(
    format!("\nMOVE # {} GUESS: ", human_moves).as_str())
{
    Ok(s) => s,
    Err(e) => { eprintln!("{}", e); return None; }
};
Defensive patterns

Strategy: try-catch

Validate before calling

// get_string_from_user_input already returns Result;
// callers should not .expect() it.
// Validate at the call site:
if let Ok(s) = get_string_from_user_input("prompt") {
    // use s
}

Type guard

// The function already returns Result<String, Box<dyn Error>>.
// Treat it as a fallible operation, not an infallible one.

Try / catch

match get_string_from_user_input(
    format!("\nMOVE # {} GUESS: ", human_moves).as_str())
{
    Ok(user_input) => { /* parse user_input */ }
    Err(e) => { eprintln!("{}", e); return None; }
}

Prevention

When it happens

Trigger: `get_string_from_user_input` returns `Err` when `io::stdin().read_line()` fails (line 405–408 of the same file). The `.expect` at line 126 fires on any such error during the human guess loop. Because the function already provides structured error information, the crash is purely a caller-side defect.

Common situations: Stdin closed or I/O error during a guess. Running the library's game logic from a test or service without a live terminal. The refactored version was improved to use `Result` internally but the call sites were not updated to match.

Related errors


AI-assisted analysis of coding-horror/basic-computer-games@5301155192 (2026-08-13). Data as JSON: /api/errors/d9cc3d1db8b45dc4. Report an issue: GitHub.