Skip to content

[RFC] Error handling in Rust runtime #54

Closed
@sapessi

Description

@sapessi

Currently, the Lambda Rust runtime declares a HandlerError type that developers can use to return an error from their handler method. While this approach works, it forces developers to write more verbose code to handle all errors and generate the relevant HandlerError objects. Developers would like to return errors automatically using the ? operator (#23).

For example:

fn my_handler(e: CustomEvent, c: lambda::Context) -> Result<CustomOutput, Error> {
    let i = event.age.parse::<u8>?;
    ...
}

In an error response, the Lambda runtime API expects two parameters: errorType and errorMessage. Optionally, we can also attach a stack trace to the error.

{
    "errorMessage" : "Error parsing age data.",
    "errorType" : "InvalidAgeException"
}

To generate an error message field we need the Err variant from the handler Result to support the Display trait. This allows us to support any Display type in the result - Error types inherently supports Display too. However, we cannot identify a way to automatically generate the error type field given a Display-compatible object that uses stable features. To address this, we plan to introduce a new trait in the runtime:

pub trait ErrorExt {
    fn error_type(&self) -> &str;
}

We'd like to deprecate this trait in the future and rely on the type name intrinsic (which is currently blocked on specialization). For context, see #1428.

The name ErrorExt comes from the extension trait conventions RFC. Based on feedback, we are open to changing this.

The runtime crate itself will provide the implementation of the ErrorExt trait for the most common errors in the standard library. Developers will have to implement the trait themselves in their own errors. We may consider adding a procedural macro to the runtime crate to automatically generate the trait implementation.

In summary, the proposed changes are:

  1. The handler type will accept any object that implements Display and ErrorExt in its Err variant.
  2. The runtime crate will use the Display trait to extract an error message and use the ISO-8859-1 charset.
  3. The runtime crate will call the error_type() function to get the value for the errorType field.
  4. If the RUST_BACKTRACE environment variable is set to 1, the runtime will use the backtrace crate to collect a stack trace as soon as the error is received.

The new handler type definition will be:

pub trait Handler<Event, Output, Error> 
where 
    Event: From<Vec<u8>>,
    Output: Into<Vec<u8>>,
    Error: Display + ErrorExt + Send + Sync,
{
    fn run(&mut self, event: Event, ctx: Context) -> Result<Output, Error>;
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions