Code Fix

初級

called `Result::unwrap()` on an `Err` value パニックの原因と直し方

文字列を数値に変換するparse()などはResult<T, E>型を返します。変換に失敗してErrになった状態でunwrap()を呼ぶと、パニックが発生します。

エラーメッセージの読み方

thread 'main' panicked at main.rs:3:32:
main.rs
ファイル名
3
行番号 — 実際にクラッシュした行
32
列番号
panicked
パニック — 実行時に回復不能な状態になったことを示します。tryやResultで捕まえない限り、そのままプロセスが終了します
called `Result::unwrap()` on an `Err` value: ParseIntError { kind: InvalidDigit }
詳細メッセージ — どの値が問題だったか

このエラーが出る典型パターン

パターン1

 1  fn main() {
 2      let input = "abc ";
                       ^
 3      let n: i32 = input.parse().unwrap();
 4      println!("{}", n);
 5  }
thread 'main' panicked at main.rs:3:32: called `Result::unwrap()` on an `Err` value: ParseIntError { kind: InvalidDigit }

parse()は変換できない文字列に対してErrを返します。Errの状態でunwrap()するとパニックします。

直し方: abc42 にします。

この問題を解いてみる →

広告
広告スロット(未設定)

パターン2

 1  fn main() {
 2      let input = "hello";
                       ^
 3      let n: i32 = input.parse().unwrap();
 4      println!("{}", n);
 5  }
thread 'main' panicked at main.rs:3:32: called `Result::unwrap()` on an `Err` value: ParseIntError { kind: InvalidDigit }

数値に見えない文字列をparseすると必ずErrになり、そのままunwrap()すればパニックします。

直し方: hello100 にします。

この問題を解いてみる →

パターン3

 1  fn main() {
 2      let input = "twelve";
                        ^
 3      let n: i32 = input.parse().unwrap();
 4      println!("{}", n);
 5  }
thread 'main' panicked at main.rs:3:32: called `Result::unwrap()` on an `Err` value: ParseIntError { kind: InvalidDigit }

ユーザー入力を数値として扱う前には、parseの結果がOkかErrかを必ず確認する必要があります。

直し方: twelve12 にします。

この問題を解いてみる →

パターン4

 1  fn main() {
 2      let input = "n/a";
                      ^
 3      let n: i32 = input.parse().unwrap();
 4      println!("{}", n);
 5  }
thread 'main' panicked at main.rs:3:32: called `Result::unwrap()` on an `Err` value: ParseIntError { kind: InvalidDigit }

空文字や記号が混ざった文字列も数値として解釈できず、parseはErrを返します。

直し方: n/a7 にします。

この問題を解いてみる →

パターン5

 1  fn main() {
 2      let input = "unknown";
                        ^
 3      let n: i32 = input.parse().unwrap();
 4      println!("{}", n);
 5  }
thread 'main' panicked at main.rs:3:32: called `Result::unwrap()` on an `Err` value: ParseIntError { kind: InvalidDigit }

parseの戻り値はResultであり、失敗する可能性が型として表現されています。

直し方: unknown99 にします。

この問題を解いてみる →

よくある誤解

「parse()は文字列を数値に変換するだけの単純な処理のはず」という思い込みは誤りです。数値に変換できない文字列が渡される可能性がある限り、戻り値はResultとして失敗も表現されます。

まとめ

called `Result::unwrap()` on an `Err` value パニックの原因と直し方は初級でつまずきやすい項目です。上の5パターンを実際に手で直すと、エラーメッセージのどこを読めばよいかが掴めます。

演習をはじめる

関連するエラー

広告
広告スロット(未設定)