However, unlike more dynamic languages, the return types are usually Result<SuccessValue, SomeErrorType>, e.g. writing to a file or a socket will get you Result<usize, io::Error>, values of which can be Ok(usize) (the number of bytes written) or Err(io::Error) (an I/O error which you can further inspect).
Although if you want to, you can use Result<T, Box<Error>> where Error is a trait implemented by types representing some error information. You then lose the ability to inspect errors other than for reporting them wholesale, but the APIs are slightly more uniform, type-wise.
You can read about all of this and more in the dedicated chapter of the official Rust Book: https://doc.rust-lang.org/book/error-handling.html.