lilydocs
HTTP APIWebSocketConsumer
HTTP2 min read

Errors and localization

Convert domain errors into an HTTP contract and localize error messages.

Built-in HttpApiError provides a status, an error code, and a safe public message. Implement IntoResponse when you need an error schema specific to your domain.

Custom error responses#

Add serde_json = "1" to your manifest. With this converter, an action can return Result<UserView, ApiError>:

errors.rs
use lilyrs::http_api::{
    HttpErrorCode, IntoResponse, Request, Response, ResponseBuilder,
    ResponseWriteError, ResponseWriteOutcome,
};

pub enum ApiError { UserNotFound }

#[lilyrs::http_api::async_trait::async_trait]
impl IntoResponse for ApiError {
    async fn write_to_response(self, response: &mut Response, request: &mut Request)
        -> Result<ResponseWriteOutcome, ResponseWriteError>
    {
        match self {
            Self::UserNotFound => {
                ResponseBuilder::new().status(404, "Not Found")
                    .json(serde_json::json!({ "message": "Kullanıcı bulunamadı" }))
                    .write_to_response(response, request).await?;
                Ok(ResponseWriteOutcome::rejected(Some(
                    HttpErrorCode::new("USER_NOT_FOUND").unwrap(),
                )))
            }
        }
    }
}

UserNotFound produces 404 and {"message":"Kullanıcı bulunamadı"}. ResponseWriteOutcome::rejected classifies the result as an expected application rejection in telemetry. If the error is written successfully, the converter returns Ok; a technical write failure is distinguished by ResponseWriteError.

Public messages and internal details#

Do not expose database connection details or token contents in a public error body. A string inside HttpApiError is not automatically published verbatim. Define your public schema deliberately.

Translation catalog#

Localization is disabled by default. Choose localization_path("./locales") or localization_catalog(catalog) on the builder. JSON locale files use HttpApiError::error_code() values as keys:

locales/tr.json
{
  "VALIDATION_ERROR": "Gönderilen bilgileri kontrol edin."
}

Language precedence is the localization header → accept-language → en. If no translation is found, the built-in public message is used.

Catalog lifecycle#

The catalog is read during build and becomes immutable. Changing the file does not automatically reload it in a running application. A new catalog is loaded on a new application startup.

Sources for this page v0.1.0

This guide is based on the reviewed framework commit.

QUICK START
Documentation
Source code