Error management


#1

Hi Folks,

I am writing a library the connect two other componets (Redis and SQLite)

Each of this component in the normal execution may return some error.

Logically the hierarchy of the error looks like this:

Error
`|- RedisError
    `- Foo
`|- SQLiteError
    `- AAA
    |- BBB
    |- CCC

Up untill now I only had function that returned an error or from SQLiteError or from RedisError, so I implemented everything as a structure.

Now I am adding features and I start to have functions that may return either error from Redis or error from SQLite

The error from SQLite are quite complex, they are not simple strings.

Ideally I was hoping to have something like a “super class”, Error, as parent of both SQLiteError and RedisError but clearly this is not how Rust works.

There is a clean way to achieve this?


#2

You very much can create a super error “class”, and this is in fact idiomatic. You can for instance have an enum which has an Redis variant and an Sql variant and write an From implementation to convert those errors to your super error.

See the rust book for a basic introduction.

See error_chain for a helper library.


#3

Someone please correct me if I am wrong - Implementing From for your super error has another huge benefit. If you have a function f which returns a Result<A, SQLiteError> and you call it inside a function which returns a Result<B, SuperError> then you propagate that sqlite error hassle free using the ? operator.

fn inner(param: u8, other_param: usize) -> Result<u8, SQLiteError> {
    ... do stuff, maybe return an Err(..) ...
}

fn outer(param: u8) -> Result<u8, SuperError> {
    let x = inner(param, 8)?;
    Ok(2x + 1)
}

#4

This is correct. Unfortunately the rust book link I posted wasn’t updated to include the ? operator, but works semantically just as try! would.


#5

Why unfortunately?


#6

Sorry, I meant “Unfortunately … wasn’t updated”


#7

+1 on error_chain. When used consistently, it makes idiomatic error handling very clean.