//! Error handling facilities use std::path::PathBuf; use thiserror::Error; use crate::{config::ListenConfig, observability::prelude::*}; /// Top-level errors // Missing docs are allowed here since that kind of information should be // encoded in the error messages themselves anyway. #[allow(missing_docs)] #[derive(Error, Debug)] pub(crate) enum Main { #[error(transparent)] ServeCommand(#[from] ServeCommand), #[error("failed to install global default tracing subscriber")] SetSubscriber(#[from] t::subscriber::SetGlobalDefaultError), #[error(transparent)] CheckConfigCommand(#[from] CheckConfigCommand), } /// Errors returned from the `serve` CLI subcommand. // Missing docs are allowed here since that kind of information should be // encoded in the error messages themselves anyway. #[allow(missing_docs)] #[derive(Error, Debug)] pub(crate) enum ServeCommand { #[error("failed to load configuration")] Config(#[from] Config), #[error("failed to initialize observability")] Observability(#[from] Observability), #[error("failed to load or create the database")] DatabaseError(#[source] crate::utils::error::Error), #[error("failed to serve requests")] Serve(#[from] Serve), #[error("failed to initialize services")] InitializeServices(#[source] crate::utils::error::Error), #[error("`server_name` change check failed")] ServerNameChanged(#[from] ServerNameChanged), } /// Errors returned from the `check-config` CLI subcommand. // Missing docs are allowed here since that kind of information should be // encoded in the error messages themselves anyway. #[allow(missing_docs)] #[derive(Error, Debug)] pub(crate) enum CheckConfigCommand { #[error("failed to validate configuration")] Config(#[from] Config), } /// Error generated if `server_name` has changed or if checking this failed // Missing docs are allowed here since that kind of information should be // encoded in the error messages themselves anyway. #[allow(missing_docs)] #[derive(Error, Debug)] pub(crate) enum ServerNameChanged { #[error("failed to check if there are any users")] NonZeroUsers(#[source] crate::utils::error::Error), #[error("failed to check if the admin bot exists")] AdminBotExists(#[source] crate::utils::error::Error), #[error("`server_name` in the database and config file differ")] Renamed, } /// Observability initialization errors // Missing docs are allowed here since that kind of information should be // encoded in the error messages themselves anyway. #[allow(missing_docs)] #[derive(Error, Debug)] pub(crate) enum Observability { // Upstream's documentation on what this error means is very sparse #[error("opentelemetry error")] Otel(#[from] opentelemetry::trace::TraceError), #[error("failed to install global default tracing subscriber")] SetSubscriber(#[from] t::subscriber::SetGlobalDefaultError), // Upstream's documentation on what this error means is very sparse #[error("tracing_flame error")] TracingFlame(#[from] tracing_flame::Error), } /// Configuration errors // Missing docs are allowed here since that kind of information should be // encoded in the error messages themselves anyway. #[allow(missing_docs)] #[derive(Error, Debug)] pub(crate) enum Config { #[error("failed to find configuration file")] Search(#[from] ConfigSearch), #[error("failed to read configuration file {1:?}")] Read(#[source] std::io::Error, PathBuf), #[error("failed to parse configuration file {1:?}")] Parse(#[source] toml::de::Error, PathBuf), #[error("failed to canonicalize path {}", .1.display())] Canonicalize(#[source] std::io::Error, PathBuf), #[error("registration token must not be empty")] RegistrationTokenEmpty, #[error("database and media paths overlap")] DatabaseMediaOverlap, } /// Errors that can occur while searching for a config file // Missing docs are allowed here since that kind of information should be // encoded in the error messages themselves anyway. #[allow(missing_docs)] #[derive(Error, Debug)] pub(crate) enum ConfigSearch { #[error("XDG Base Directory error")] Xdg(#[from] xdg::BaseDirectoriesError), #[error("no relevant configuration files found in XDG Base Directories")] NotFound, } /// Errors serving traffic // Missing docs are allowed here since that kind of information should be // encoded in the error messages themselves anyway. #[allow(missing_docs)] #[derive(Error, Debug)] pub(crate) enum Serve { #[error("no listeners were specified in the configuration file")] NoListeners, #[error( "listener {0} requested TLS, but no TLS cert was specified in the \ configuration file. Please set 'tls.certs' and 'tls.key'" )] NoTlsCerts(ListenConfig), #[error("failed to read TLS cert and key files at {certs:?} and {key:?}")] LoadCerts { certs: String, key: String, #[source] err: std::io::Error, }, #[error("failed to run request listener on {1}")] Listen(#[source] std::io::Error, ListenConfig), #[error( "federation self-test failed (set `federation.self_test = false` in \ config to disable)" )] FederationSelfTestFailed(#[source] crate::Error), }