diff --git a/exercises/error_handling/errors5.rs b/exercises/error_handling/errors5.rs
new file mode 100644
index 0000000..1b11800
--- /dev/null
+++ b/exercises/error_handling/errors5.rs
@@ -0,0 +1,53 @@
+// errors5.rs
+
+// This program uses a completed version of the code from errors4.
+// It won't compile right now! Why?
+// Execute `rustlings hint errors5` for hints!
+
+// I AM NOT DONE
+
+use std::error;
+use std::fmt;
+use std::num::ParseIntError;
+
+// TODO: update the return type of `main()` to make this compile.
+fn main() -> Result<(), ParseIntError> {
+    let pretend_user_input = "42";
+    let x: i64 = pretend_user_input.parse()?;
+    println!("output={:?}", PositiveNonzeroInteger::new(x)?);
+    Ok(())
+}
+
+// Don't change anything below this line.
+
+#[derive(PartialEq, Debug)]
+struct PositiveNonzeroInteger(u64);
+
+#[derive(PartialEq, Debug)]
+enum CreationError {
+    Negative,
+    Zero,
+}
+
+impl PositiveNonzeroInteger {
+    fn new(value: i64) -> Result<PositiveNonzeroInteger, CreationError> {
+        match value {
+            x if x < 0 => Err(CreationError::Negative),
+            x if x == 0 => Err(CreationError::Zero),
+            x => Ok(PositiveNonzeroInteger(x as u64))
+        }
+    }
+}
+
+// This is required so that `CreationError` can implement `error::Error`.
+impl fmt::Display for CreationError {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        let description = match *self {
+            CreationError::Negative => "Number is negative",
+            CreationError::Zero => "Number is zero",
+        };
+        f.write_str(description)
+    }
+}
+
+impl error::Error for CreationError {}
diff --git a/exercises/error_handling/errors6.rs b/exercises/error_handling/errors6.rs
new file mode 100644
index 0000000..cee7250
--- /dev/null
+++ b/exercises/error_handling/errors6.rs
@@ -0,0 +1,86 @@
+// errors6.rs
+
+// Using catch-all error types like `Box<dyn error::Error>` isn't recommended
+// for library code, where callers might want to make decisions based on the
+// error content, instead of printing it out or propagating it further. Here,
+// we define a custom error type to make it possible for callers to decide
+// what to do next when our function returns an error.
+
+// Make these tests pass! Execute `rustlings hint errors6` for hints :)
+
+// I AM NOT DONE
+
+// This is a custom error type that we will be using in `parse_pos_nonzero()`.
+#[derive(PartialEq, Debug)]
+enum ParsePosNonzeroError {
+    CreationError,
+    ParseIntError
+}
+
+fn parse_pos_nonzero(s: &str)
+    -> Result<PositiveNonzeroInteger, ParsePosNonzeroError>
+{
+    // TODO: change this to return an appropriate error instead of panicking
+    // when `parse()` returns an error.
+    let x: i64 = s.parse().unwrap();
+    PositiveNonzeroInteger::new(x)
+        .or(Err(ParsePosNonzeroError::CreationError))
+}
+
+// Don't change anything below this line.
+
+#[derive(PartialEq, Debug)]
+struct PositiveNonzeroInteger(u64);
+
+#[derive(PartialEq, Debug)]
+enum CreationError {
+    Negative,
+    Zero,
+}
+
+impl PositiveNonzeroInteger {
+    fn new(value: i64) -> Result<PositiveNonzeroInteger, CreationError> {
+        match value {
+            x if x < 0 => Err(CreationError::Negative),
+            x if x == 0 => Err(CreationError::Zero),
+            x => Ok(PositiveNonzeroInteger(x as u64))
+        }
+    }
+}
+
+#[cfg(test)]
+mod test {
+    use super::*;
+
+    #[test]
+    fn test_parse_error() {
+        assert_eq!(
+            parse_pos_nonzero("not a number"),
+            Err(ParsePosNonzeroError::ParseIntError)
+        );
+    }
+
+    #[test]
+    fn test_negative() {
+        assert_eq!(
+            parse_pos_nonzero("-555"),
+            Err(ParsePosNonzeroError::CreationError)
+        );
+    }
+
+    #[test]
+    fn test_zero() {
+        assert_eq!(
+            parse_pos_nonzero("0"),
+            Err(ParsePosNonzeroError::CreationError)
+        );
+    }
+
+    #[test]
+    fn test_positive() {
+        assert_eq!(
+            parse_pos_nonzero("42"),
+            Ok(PositiveNonzeroInteger(42))
+        );
+    }
+}
diff --git a/exercises/error_handling/errorsn.rs b/exercises/error_handling/errorsn.rs
deleted file mode 100644
index 5fe212b..0000000
--- a/exercises/error_handling/errorsn.rs
+++ /dev/null
@@ -1,117 +0,0 @@
-// errorsn.rs
-// This is a bigger error exercise than the previous ones!
-// You can do it! :)
-//
-// Edit the `read_and_validate` function ONLY. Don't create any Errors
-// that do not already exist.
-//
-// So many things could go wrong!
-//
-// - Reading from stdin could produce an io::Error
-// - Parsing the input could produce a num::ParseIntError
-// - Validating the input could produce a CreationError (defined below)
-//
-// How can we lump these errors into one general error? That is, what
-// type goes where the question marks are, and how do we return
-// that type from the body of read_and_validate?
-//
-// Execute `rustlings hint errorsn` for hints :)
-
-// I AM NOT DONE
-
-use std::error;
-use std::fmt;
-use std::io;
-
-// PositiveNonzeroInteger is a struct defined below the tests.
-fn read_and_validate(b: &mut dyn io::BufRead) -> Result<PositiveNonzeroInteger, ???> {
-    let mut line = String::new();
-    b.read_line(&mut line);
-    let num: i64 = line.trim().parse();
-    let answer = PositiveNonzeroInteger::new(num);
-    answer
-}
-
-//
-// Nothing below this needs to be modified
-//
-
-// This is a test helper function that turns a &str into a BufReader.
-fn test_with_str(s: &str) -> Result<PositiveNonzeroInteger, Box<dyn error::Error>> {
-    let mut b = io::BufReader::new(s.as_bytes());
-    read_and_validate(&mut b)
-}
-
-#[test]
-fn test_success() {
-    let x = test_with_str("42\n");
-    assert_eq!(PositiveNonzeroInteger(42), x.unwrap());
-}
-
-#[test]
-fn test_not_num() {
-    let x = test_with_str("eleven billion\n");
-    assert!(x.is_err());
-}
-
-#[test]
-fn test_non_positive() {
-    let x = test_with_str("-40\n");
-    assert!(x.is_err());
-}
-
-#[test]
-fn test_ioerror() {
-    struct Broken;
-    impl io::Read for Broken {
-        fn read(&mut self, _buf: &mut [u8]) -> io::Result<usize> {
-            Err(io::Error::new(io::ErrorKind::BrokenPipe, "uh-oh!"))
-        }
-    }
-    let mut b = io::BufReader::new(Broken);
-    assert!(read_and_validate(&mut b).is_err());
-    assert_eq!("uh-oh!", read_and_validate(&mut b).unwrap_err().to_string());
-}
-
-#[derive(PartialEq, Debug)]
-struct PositiveNonzeroInteger(u64);
-
-impl PositiveNonzeroInteger {
-    fn new(value: i64) -> Result<PositiveNonzeroInteger, CreationError> {
-        if value == 0 {
-            Err(CreationError::Zero)
-        } else if value < 0 {
-            Err(CreationError::Negative)
-        } else {
-            Ok(PositiveNonzeroInteger(value as u64))
-        }
-    }
-}
-
-#[test]
-fn test_positive_nonzero_integer_creation() {
-    assert!(PositiveNonzeroInteger::new(10).is_ok());
-    assert_eq!(
-        Err(CreationError::Negative),
-        PositiveNonzeroInteger::new(-10)
-    );
-    assert_eq!(Err(CreationError::Zero), PositiveNonzeroInteger::new(0));
-}
-
-#[derive(PartialEq, Debug)]
-enum CreationError {
-    Negative,
-    Zero,
-}
-
-impl fmt::Display for CreationError {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        let description = match *self {
-            CreationError::Negative => "Number is negative",
-            CreationError::Zero => "Number is zero",
-        };
-        f.write_str(description)
-    }
-}
-
-impl error::Error for CreationError {}
diff --git a/info.toml b/info.toml
index 55875d7..63eb78b 100644
--- a/info.toml
+++ b/info.toml
@@ -499,42 +499,49 @@ It should be doing some checking, returning an `Err` result if those checks fail
 returning an `Ok` result if those checks determine that everything is... okay :)"""
 
 [[exercises]]
-name = "errorsn"
-path = "exercises/error_handling/errorsn.rs"
-mode = "test"
+name = "errors5"
+path = "exercises/error_handling/errors5.rs"
+mode = "compile"
 hint = """
-First hint: To figure out what type should go where the ??? is, take a look
-at the test helper function `test_with_str`, since it returns whatever
-`read_and_validate` returns and `test_with_str` has its signature fully
-specified.
-
-
-Next hint: There are three places in `read_and_validate` that we call a
-function that returns a `Result` (that is, the functions might fail).
-Apply the `?` operator on those calls so that we return immediately from
-`read_and_validate` if those function calls fail.
-
+Hint: There are two different possible `Result` types produced within
+`main()`, which are propagated using `?` operators. How do we declare a
+return type from `main()` that allows both?
 
 Another hint: under the hood, the `?` operator calls `From::from`
-on the error value to convert it to a boxed trait object, a Box<dyn error::Error>,
-which is polymorphic-- that means that lots of different kinds of errors
-can be returned from the same function because all errors act the same
-since they all implement the `error::Error` trait.
+on the error value to convert it to a boxed trait object, a
+`Box<dyn error::Error>`, which is polymorphic-- that means that lots of
+different kinds of errors can be returned from the same function because
+all errors act the same since they all implement the `error::Error` trait.
 Check out this section of the book:
 https://doc.rust-lang.org/book/ch09-02-recoverable-errors-with-result.html#a-shortcut-for-propagating-errors-the--operator
 
+This exercise uses some concepts that we won't get to until later in the
+course, like `Box` and the `From` trait. It's not important to understand
+them in detail right now, but you can read ahead if you like.
 
-Another another hint: Note that because the `?` operator returns
-the *unwrapped* value in the `Ok` case, if we want to return a `Result` from
-`read_and_validate` for *its* success case, we'll have to rewrap a value
-that we got from the return value of a `?`ed call in an `Ok`-- this will
-look like `Ok(something)`.
+Read more about boxing errors:
+https://doc.rust-lang.org/stable/rust-by-example/error/multiple_error_types/boxing_errors.html
 
+Read more about using the `?` operator with boxed errors:
+https://doc.rust-lang.org/stable/rust-by-example/error/multiple_error_types/reenter_question_mark.html
+"""
 
-Another another another hint: `Result`s must be "used", that is, you'll
-get a warning if you don't handle a `Result` that you get in your
-function. Read more about that in the `std::result` module docs:
-https://doc.rust-lang.org/std/result/#results-must-be-used"""
+[[exercises]]
+name = "errors6"
+path = "exercises/error_handling/errors6.rs"
+mode = "test"
+hint = """
+This exercise uses a completed version of `PositiveNonzeroInteger` from
+the errors4.
+
+Below the TODO line, there is an example of using the `.or()` method
+on a `Result` to transform one type of error into another. Try using
+something similar on the `Result` from `parse()`. You might use the `?`
+operator to return early from the function, or you might use a `match`
+expression, or maybe there's another way!
+
+Read more about `.or()` in the `std::result` documentation:
+https://doc.rust-lang.org/std/result/enum.Result.html#method.or"""
 
 # Generics