Back to Blog

Rust Error Handling in Tauri Apps | Custom Error Types with thiserror

Sandy LaneSandy Lane

Video: Rust Error Handling in Tauri Apps | Custom Error Types with thiserror by Taught by Celeste AI - AI Coding Coach

Watch full page →

Rust Error Handling in Tauri Apps | Custom Error Types with thiserror

Master professional error handling in Tauri desktop applications by leveraging Rust's powerful type system. This tutorial demonstrates how to create custom error types using the thiserror crate, serialize errors with serde, and integrate these errors seamlessly into a React frontend for clear user feedback.

Code

use serde::Serialize;
use thiserror::Error;

// Define custom error types for the app
#[derive(Debug, Error, Serialize)]
pub enum AppError {
  #[error("Validation error: {0}")]
  ValidationError(String),

  #[error("Not found error: {0}")]
  NotFoundError(String),

  #[error("Permission denied: {0}")]
  PermissionDenied(String),
}

// Example Tauri command: validate an email address
#[tauri::command]
pub fn validate_email(email: String) -> Result {
  if email.trim().is_empty() {
    return Err(AppError::ValidationError("Email cannot be empty".into()));
  }
  if !email.contains('@') {
    return Err(AppError::ValidationError("Email must contain '@'".into()));
  }
  let domain = email.split('@').nth(1).unwrap_or("");
  if !domain.contains('.') {
    return Err(AppError::ValidationError("Email domain is invalid".into()));
  }
  Ok("Email is valid!".into())
}

// Example Tauri command: find a user by ID
#[tauri::command]
pub fn find_user(user_id: u32) -> Result {
  let users = vec![1, 2, 3]; // Fake user IDs
  if users.contains(&user_id) {
    Ok(format!("User {} found", user_id))
  } else {
    Err(AppError::NotFoundError(format!("User {} not found", user_id)))
  }
}

// Example Tauri command: delete user with permission check
#[tauri::command]
pub fn delete_user(user_id: u32, is_admin: bool) -> Result {
  if !is_admin {
    return Err(AppError::PermissionDenied("Only admins can delete users".into()));
  }
  // Pretend to delete user here
  Ok(format!("User {} deleted", user_id))
}

Key Points

  • The thiserror crate simplifies defining custom error types with descriptive messages.
  • Deriving Serialize from serde enables sending structured errors as JSON to the frontend.
  • Using Result<T, AppError> in Tauri commands cleanly separates success and error cases.
  • Frontend React apps can catch Rust errors as exceptions and display user-friendly messages.
  • Common error patterns include validation errors, not found errors, and permission denied errors for robust app logic.