Merge pull request 'migrate to this error, garage-v2' (#1219) from thiserror-2 into main-v2

Reviewed-on: https://git.deuxfleurs.fr/Deuxfleurs/garage/pulls/1219
Reviewed-by: Alex <lx@deuxfleurs.fr>
This commit is contained in:
Alex
2025-11-12 08:05:43 +00:00
25 changed files with 177 additions and 214 deletions

58
Cargo.lock generated
View File

@@ -1112,20 +1112,6 @@ version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
[[package]]
name = "err-derive"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c34a887c8df3ed90498c1c437ce21f211c8e27672921a8ffa293cb8d6d4caa9e"
dependencies = [
"proc-macro-error",
"proc-macro2",
"quote",
"rustversion",
"syn 1.0.109",
"synstructure 0.12.6",
]
[[package]]
name = "errno"
version = "0.3.10"
@@ -1355,7 +1341,6 @@ dependencies = [
"async-trait",
"bytesize",
"chrono",
"err-derive",
"format_table",
"futures",
"garage_api_common",
@@ -1373,6 +1358,7 @@ dependencies = [
"prometheus",
"serde",
"serde_json",
"thiserror 2.0.12",
"tokio",
"tracing",
"url",
@@ -1388,7 +1374,6 @@ dependencies = [
"chrono",
"crc-fast",
"crypto-common",
"err-derive",
"futures",
"garage_model",
"garage_table",
@@ -1407,6 +1392,7 @@ dependencies = [
"serde_json",
"sha1",
"sha2",
"thiserror 2.0.12",
"tokio",
"tracing",
"url",
@@ -1417,7 +1403,6 @@ name = "garage_api_k2v"
version = "2.1.0"
dependencies = [
"base64 0.21.7",
"err-derive",
"futures",
"garage_api_common",
"garage_model",
@@ -1430,6 +1415,7 @@ dependencies = [
"percent-encoding",
"serde",
"serde_json",
"thiserror 2.0.12",
"tokio",
"tracing",
"url",
@@ -1445,7 +1431,6 @@ dependencies = [
"bytes",
"chrono",
"crc-fast",
"err-derive",
"form_urlencoded",
"futures",
"garage_api_common",
@@ -1473,6 +1458,7 @@ dependencies = [
"serde_json",
"sha1",
"sha2",
"thiserror 2.0.12",
"tokio",
"tokio-stream",
"tokio-util 0.7.14",
@@ -1508,7 +1494,6 @@ dependencies = [
name = "garage_db"
version = "2.1.0"
dependencies = [
"err-derive",
"fjall",
"heed",
"mktemp",
@@ -1516,6 +1501,7 @@ dependencies = [
"r2d2",
"r2d2_sqlite",
"rusqlite",
"thiserror 2.0.12",
"tracing",
]
@@ -1528,7 +1514,6 @@ dependencies = [
"base64 0.21.7",
"blake2",
"chrono",
"err-derive",
"futures",
"garage_block",
"garage_db",
@@ -1542,6 +1527,7 @@ dependencies = [
"rand 0.8.5",
"serde",
"serde_bytes",
"thiserror 2.0.12",
"tokio",
"tracing",
"zstd",
@@ -1554,7 +1540,6 @@ dependencies = [
"arc-swap",
"bytes",
"cfg-if",
"err-derive",
"futures",
"hex",
"kuska-handshake",
@@ -1567,6 +1552,7 @@ dependencies = [
"rand 0.8.5",
"rmp-serde",
"serde",
"thiserror 2.0.12",
"tokio",
"tokio-stream",
"tokio-util 0.7.14",
@@ -1579,7 +1565,6 @@ dependencies = [
"arc-swap",
"async-trait",
"bytesize",
"err-derive",
"format_table",
"futures",
"garage_net",
@@ -1600,6 +1585,7 @@ dependencies = [
"serde",
"serde_bytes",
"serde_json",
"thiserror 2.0.12",
"tokio",
"tracing",
]
@@ -1634,7 +1620,6 @@ dependencies = [
"blake2",
"bytesize",
"chrono",
"err-derive",
"futures",
"garage_db",
"garage_net",
@@ -1651,6 +1636,7 @@ dependencies = [
"serde",
"serde_json",
"sha2",
"thiserror 2.0.12",
"tokio",
"toml",
"tracing",
@@ -1661,7 +1647,6 @@ dependencies = [
name = "garage_web"
version = "2.1.0"
dependencies = [
"err-derive",
"garage_api_common",
"garage_api_s3",
"garage_model",
@@ -1672,6 +1657,7 @@ dependencies = [
"hyper 1.6.0",
"opentelemetry",
"percent-encoding",
"thiserror 2.0.12",
"tokio",
"tracing",
]
@@ -2464,7 +2450,7 @@ dependencies = [
"serde",
"serde_json",
"sha2",
"thiserror 1.0.69",
"thiserror 2.0.12",
"tokio",
"tracing-subscriber",
]
@@ -4281,18 +4267,6 @@ dependencies = [
"crossbeam-queue",
]
[[package]]
name = "synstructure"
version = "0.12.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.109",
"unicode-xid",
]
[[package]]
name = "synstructure"
version = "0.13.1"
@@ -4812,12 +4786,6 @@ version = "0.1.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af"
[[package]]
name = "unicode-xid"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853"
[[package]]
name = "universal-hash"
version = "0.5.1"
@@ -5343,7 +5311,7 @@ dependencies = [
"proc-macro2",
"quote",
"syn 2.0.100",
"synstructure 0.13.1",
"synstructure",
]
[[package]]
@@ -5404,7 +5372,7 @@ dependencies = [
"proc-macro2",
"quote",
"syn 2.0.100",
"synstructure 0.13.1",
"synstructure",
]
[[package]]

View File

@@ -51,7 +51,6 @@ cfg-if = "1.0"
chrono = { version = "0.4", features = ["serde"] }
crc-fast = "1.6"
crypto-common = "0.1"
err-derive = "0.3"
gethostname = "0.4"
git-version = "0.3.4"
hex = "0.4"
@@ -138,7 +137,7 @@ prometheus = "0.13"
aws-sigv4 = { version = "1.1", default-features = false }
hyper-rustls = { version = "0.26", default-features = false, features = ["http1", "http2", "ring", "rustls-native-certs"] }
log = "0.4"
thiserror = "1.0"
thiserror = "2.0"
# ---- used only as build / dev dependencies ----
assert-json-diff = "2.0"

View File

@@ -26,7 +26,7 @@ argon2.workspace = true
async-trait.workspace = true
bytesize.workspace = true
chrono.workspace = true
err-derive.workspace = true
thiserror.workspace = true
hex.workspace = true
paste.workspace = true
tracing.workspace = true

View File

@@ -1,8 +1,8 @@
use std::convert::TryFrom;
use err_derive::Error;
use hyper::header::HeaderValue;
use hyper::{HeaderMap, StatusCode};
use thiserror::Error;
pub use garage_model::helper::error::Error as HelperError;
@@ -16,36 +16,33 @@ use garage_api_common::helpers::*;
/// Errors of this crate
#[derive(Debug, Error)]
pub enum Error {
#[error(display = "{}", _0)]
#[error("{0}")]
/// Error from common error
Common(#[error(source)] CommonError),
Common(#[from] CommonError),
// Category: cannot process
/// The admin API token does not exist
#[error(display = "Admin token not found: {}", _0)]
#[error("Admin token not found: {0}")]
NoSuchAdminToken(String),
/// The API access key does not exist
#[error(display = "Access key not found: {}", _0)]
#[error("Access key not found: {00}")]
NoSuchAccessKey(String),
/// The requested block does not exist
#[error(display = "Block not found: {}", _0)]
#[error("Block not found: {0}")]
NoSuchBlock(String),
/// The requested worker does not exist
#[error(display = "Worker not found: {}", _0)]
#[error("Worker not found: {0}")]
NoSuchWorker(u64),
/// The object requested don't exists
#[error(display = "Key not found")]
#[error("Key not found")]
NoSuchKey,
/// In Import key, the key already exists
#[error(
display = "Key {} already exists in data store. Even if it is deleted, we can't let you create a new key with the same ID. Sorry.",
_0
)]
#[error("Key {0} already exists in data store. Even if it is deleted, we can't let you create a new key with the same ID. Sorry.")]
KeyAlreadyExists(String),
}

View File

@@ -23,7 +23,7 @@ bytes.workspace = true
chrono.workspace = true
crc-fast.workspace = true
crypto-common.workspace = true
err-derive.workspace = true
thiserror.workspace = true
hex.workspace = true
hmac.workspace = true
md-5.workspace = true

View File

@@ -1,7 +1,7 @@
use std::convert::TryFrom;
use err_derive::Error;
use hyper::StatusCode;
use thiserror::Error;
use garage_util::error::Error as GarageError;
@@ -12,48 +12,48 @@ use garage_model::helper::error::Error as HelperError;
pub enum CommonError {
// ---- INTERNAL ERRORS ----
/// Error related to deeper parts of Garage
#[error(display = "Internal error: {}", _0)]
InternalError(#[error(source)] GarageError),
#[error("Internal error: {0}")]
InternalError(#[from] GarageError),
/// Error related to Hyper
#[error(display = "Internal error (Hyper error): {}", _0)]
Hyper(#[error(source)] hyper::Error),
#[error("Internal error (Hyper error): {0}")]
Hyper(#[from] hyper::Error),
/// Error related to HTTP
#[error(display = "Internal error (HTTP error): {}", _0)]
Http(#[error(source)] http::Error),
#[error("Internal error (HTTP error): {0}")]
Http(#[from] http::Error),
// ---- GENERIC CLIENT ERRORS ----
/// Proper authentication was not provided
#[error(display = "Forbidden: {}", _0)]
#[error("Forbidden: {0}")]
Forbidden(String),
/// Generic bad request response with custom message
#[error(display = "Bad request: {}", _0)]
#[error("Bad request: {0}")]
BadRequest(String),
/// The client sent a header with invalid value
#[error(display = "Invalid header value: {}", _0)]
InvalidHeader(#[error(source)] hyper::header::ToStrError),
#[error("Invalid header value: {0}")]
InvalidHeader(#[from] hyper::header::ToStrError),
// ---- SPECIFIC ERROR CONDITIONS ----
// These have to be error codes referenced in the S3 spec here:
// https://docs.aws.amazon.com/AmazonS3/latest/API/ErrorResponses.html#ErrorCodeList
/// The bucket requested don't exists
#[error(display = "Bucket not found: {}", _0)]
#[error("Bucket not found: {0}")]
NoSuchBucket(String),
/// Tried to create a bucket that already exist
#[error(display = "Bucket already exists")]
#[error("Bucket already exists")]
BucketAlreadyExists,
/// Tried to delete a non-empty bucket
#[error(display = "Tried to delete a non-empty bucket")]
#[error("Tried to delete a non-empty bucket")]
BucketNotEmpty,
// Category: bad request
/// Bucket name is not valid according to AWS S3 specs
#[error(display = "Invalid bucket name: {}", _0)]
#[error("Invalid bucket name: {0}")]
InvalidBucketName(String),
}

View File

@@ -1,4 +1,4 @@
use err_derive::Error;
use thiserror::Error;
use crate::common_error::CommonError;
pub use crate::common_error::{CommonErrorDerivative, OkOrBadRequest, OkOrInternalError};
@@ -6,21 +6,21 @@ pub use crate::common_error::{CommonErrorDerivative, OkOrBadRequest, OkOrInterna
/// Errors of this crate
#[derive(Debug, Error)]
pub enum Error {
#[error(display = "{}", _0)]
#[error("{0}")]
/// Error from common error
Common(CommonError),
/// Authorization Header Malformed
#[error(display = "Authorization header malformed, unexpected scope: {}", _0)]
#[error("Authorization header malformed, unexpected scope: {0}")]
AuthorizationHeaderMalformed(String),
// Category: bad request
/// The request contained an invalid UTF-8 sequence in its path or in other parameters
#[error(display = "Invalid UTF-8: {}", _0)]
InvalidUtf8Str(#[error(source)] std::str::Utf8Error),
#[error("Invalid UTF-8: {0}")]
InvalidUtf8Str(#[from] std::str::Utf8Error),
/// The provided digest (checksum) value was invalid
#[error(display = "Invalid digest: {}", _0)]
#[error("Invalid digest: {0}")]
InvalidDigest(String),
}

View File

@@ -20,7 +20,7 @@ garage_util = { workspace = true, features = [ "k2v" ] }
garage_api_common.workspace = true
base64.workspace = true
err-derive.workspace = true
thiserror.workspace = true
tracing.workspace = true
futures.workspace = true

View File

@@ -1,6 +1,6 @@
use err_derive::Error;
use hyper::header::HeaderValue;
use hyper::{HeaderMap, StatusCode};
use thiserror::Error;
pub(crate) use garage_api_common::common_error::pass_helper_error;
use garage_api_common::common_error::{commonErrorDerivative, CommonError};
@@ -14,38 +14,38 @@ use garage_api_common::signature::error::Error as SignatureError;
/// Errors of this crate
#[derive(Debug, Error)]
pub enum Error {
#[error(display = "{}", _0)]
#[error("{0}")]
/// Error from common error
Common(#[error(source)] CommonError),
Common(#[from] CommonError),
// Category: cannot process
/// Authorization Header Malformed
#[error(display = "Authorization header malformed, unexpected scope: {}", _0)]
#[error("Authorization header malformed, unexpected scope: {0}")]
AuthorizationHeaderMalformed(String),
/// The provided digest (checksum) value was invalid
#[error(display = "Invalid digest: {}", _0)]
#[error("Invalid digest: {0}")]
InvalidDigest(String),
/// The object requested don't exists
#[error(display = "Key not found")]
#[error("Key not found")]
NoSuchKey,
/// Some base64 encoded data was badly encoded
#[error(display = "Invalid base64: {}", _0)]
InvalidBase64(#[error(source)] base64::DecodeError),
#[error("Invalid base64: {0}")]
InvalidBase64(#[from] base64::DecodeError),
/// Invalid causality token
#[error(display = "Invalid causality token")]
#[error("Invalid causality token")]
InvalidCausalityToken,
/// The client asked for an invalid return format (invalid Accept header)
#[error(display = "Not acceptable: {}", _0)]
#[error("Not acceptable: {0}")]
NotAcceptable(String),
/// The request contained an invalid UTF-8 sequence in its path or in other parameters
#[error(display = "Invalid UTF-8: {}", _0)]
InvalidUtf8Str(#[error(source)] std::str::Utf8Error),
#[error("Invalid UTF-8: {0}")]
InvalidUtf8Str(#[from] std::str::Utf8Error),
}
commonErrorDerivative!(Error);

View File

@@ -28,7 +28,7 @@ base64.workspace = true
bytes.workspace = true
chrono.workspace = true
crc-fast.workspace = true
err-derive.workspace = true
thiserror.workspace = true
hex.workspace = true
hmac.workspace = true
tracing.workspace = true

View File

@@ -1,8 +1,8 @@
use std::convert::TryInto;
use err_derive::Error;
use hyper::header::HeaderValue;
use hyper::{HeaderMap, StatusCode};
use thiserror::Error;
use garage_model::helper::error::Error as HelperError;
@@ -25,67 +25,67 @@ use crate::xml as s3_xml;
/// Errors of this crate
#[derive(Debug, Error)]
pub enum Error {
#[error(display = "{}", _0)]
#[error("{0}")]
/// Error from common error
Common(#[error(source)] CommonError),
Common(#[from] CommonError),
// Category: cannot process
/// Authorization Header Malformed
#[error(display = "Authorization header malformed, unexpected scope: {}", _0)]
#[error("Authorization header malformed, unexpected scope: {0}")]
AuthorizationHeaderMalformed(String),
/// The object requested don't exists
#[error(display = "Key not found")]
#[error("Key not found")]
NoSuchKey,
/// The multipart upload requested don't exists
#[error(display = "Upload not found")]
#[error("Upload not found")]
NoSuchUpload,
/// Precondition failed (e.g. x-amz-copy-source-if-match)
#[error(display = "At least one of the preconditions you specified did not hold")]
#[error("At least one of the preconditions you specified did not hold")]
PreconditionFailed,
/// Parts specified in CMU request do not match parts actually uploaded
#[error(display = "Parts given to CompleteMultipartUpload do not match uploaded parts")]
#[error("Parts given to CompleteMultipartUpload do not match uploaded parts")]
InvalidPart,
/// Parts given to CompleteMultipartUpload were not in ascending order
#[error(display = "Parts given to CompleteMultipartUpload were not in ascending order")]
#[error("Parts given to CompleteMultipartUpload were not in ascending order")]
InvalidPartOrder,
/// In CompleteMultipartUpload: not enough data
/// (here we are more lenient than AWS S3)
#[error(display = "Proposed upload is smaller than the minimum allowed object size")]
#[error("Proposed upload is smaller than the minimum allowed object size")]
EntityTooSmall,
// Category: bad request
/// The request contained an invalid UTF-8 sequence in its path or in other parameters
#[error(display = "Invalid UTF-8: {}", _0)]
InvalidUtf8Str(#[error(source)] std::str::Utf8Error),
#[error("Invalid UTF-8: {0}")]
InvalidUtf8Str(#[from] std::str::Utf8Error),
/// The request used an invalid path
#[error(display = "Invalid UTF-8: {}", _0)]
InvalidUtf8String(#[error(source)] std::string::FromUtf8Error),
#[error("Invalid UTF-8: {0}")]
InvalidUtf8String(#[from] std::string::FromUtf8Error),
/// The client sent invalid XML data
#[error(display = "Invalid XML: {}", _0)]
#[error("Invalid XML: {0}")]
InvalidXml(String),
/// The client sent a range header with invalid value
#[error(display = "Invalid HTTP range: {:?}", _0)]
InvalidRange(#[error(from)] (http_range::HttpRangeParseError, u64)),
#[error("Invalid HTTP range: {0:?}")]
InvalidRange((http_range::HttpRangeParseError, u64)),
/// The client sent a range header with invalid value
#[error(display = "Invalid encryption algorithm: {:?}, should be AES256", _0)]
#[error("Invalid encryption algorithm: {0:?}, should be AES256")]
InvalidEncryptionAlgorithm(String),
/// The provided digest (checksum) value was invalid
#[error(display = "Invalid digest: {}", _0)]
#[error("Invalid digest: {0}")]
InvalidDigest(String),
/// The client sent a request for an action not supported by garage
#[error(display = "Unimplemented action: {}", _0)]
#[error("Unimplemented action: {0}")]
NotImplemented(String),
}
@@ -99,6 +99,12 @@ impl From<HelperError> for Error {
}
}
impl From<(http_range::HttpRangeParseError, u64)> for Error {
fn from(err: (http_range::HttpRangeParseError, u64)) -> Error {
Error::InvalidRange(err)
}
}
impl From<roxmltree::Error> for Error {
fn from(err: roxmltree::Error) -> Self {
Self::InvalidXml(format!("{}", err))

View File

@@ -12,7 +12,7 @@ readme = "../../README.md"
path = "lib.rs"
[dependencies]
err-derive.workspace = true
thiserror.workspace = true
tracing.workspace = true
heed = { workspace = true, optional = true }

View File

@@ -20,7 +20,7 @@ use std::cell::Cell;
use std::path::PathBuf;
use std::sync::Arc;
use err_derive::Error;
use thiserror::Error;
pub use open::*;
@@ -44,7 +44,7 @@ pub type TxValueIter<'a> = Box<dyn std::iter::Iterator<Item = TxOpResult<(Value,
// ----
#[derive(Debug, Error)]
#[error(display = "{}", _0)]
#[error("{0}")]
pub struct Error(pub Cow<'static, str>);
impl From<std::io::Error> for Error {
@@ -56,7 +56,7 @@ impl From<std::io::Error> for Error {
pub type Result<T> = std::result::Result<T, Error>;
#[derive(Debug, Error)]
#[error(display = "{}", _0)]
#[error("{0}")]
pub struct TxOpError(pub(crate) Error);
pub type TxOpResult<T> = std::result::Result<T, TxOpError>;

View File

@@ -25,7 +25,7 @@ argon2.workspace = true
async-trait.workspace = true
blake2.workspace = true
chrono.workspace = true
err-derive.workspace = true
thiserror.workspace = true
hex.workspace = true
http.workspace = true
base64.workspace = true

View File

@@ -321,15 +321,15 @@ impl Garage {
Ok(())
}
pub fn bucket_helper(&self) -> helper::bucket::BucketHelper {
pub fn bucket_helper(&self) -> helper::bucket::BucketHelper<'_> {
helper::bucket::BucketHelper(self)
}
pub fn key_helper(&self) -> helper::key::KeyHelper {
pub fn key_helper(&self) -> helper::key::KeyHelper<'_> {
helper::key::KeyHelper(self)
}
pub async fn locked_helper(&self) -> helper::locked::LockedHelper {
pub async fn locked_helper(&self) -> helper::locked::LockedHelper<'_> {
let lock = self.bucket_lock.lock().await;
helper::locked::LockedHelper(self, Some(lock))
}

View File

@@ -1,24 +1,24 @@
use err_derive::Error;
use serde::{Deserialize, Serialize};
use thiserror::Error;
use garage_util::error::Error as GarageError;
#[derive(Debug, Error, Serialize, Deserialize)]
pub enum Error {
#[error(display = "Internal error: {}", _0)]
Internal(#[error(source)] GarageError),
#[error("Internal error: {0}")]
Internal(#[from] GarageError),
#[error(display = "Bad request: {}", _0)]
#[error("Bad request: {0}")]
BadRequest(String),
/// Bucket name is not valid according to AWS S3 specs
#[error(display = "Invalid bucket name: {}", _0)]
#[error("Invalid bucket name: {0}")]
InvalidBucketName(String),
#[error(display = "Access key not found: {}", _0)]
#[error("Access key not found: {0}")]
NoSuchAccessKey(String),
#[error(display = "Bucket not found: {}", _0)]
#[error("Bucket not found: {0}")]
NoSuchBucket(String),
}

View File

@@ -30,7 +30,7 @@ rand.workspace = true
log.workspace = true
arc-swap.workspace = true
err-derive.workspace = true
thiserror.workspace = true
bytes.workspace = true
cfg-if.workspace = true

View File

@@ -159,7 +159,7 @@ where
pub(crate) type DynEndpoint = Box<dyn GenericEndpoint + Send + Sync>;
pub(crate) trait GenericEndpoint {
fn handle(&self, req_enc: ReqEnc, from: NodeID) -> BoxFuture<Result<RespEnc, Error>>;
fn handle(&self, req_enc: ReqEnc, from: NodeID) -> BoxFuture<'_, Result<RespEnc, Error>>;
fn drop_handler(&self);
fn clone_endpoint(&self) -> DynEndpoint;
}
@@ -175,7 +175,7 @@ where
M: Message,
H: StreamingEndpointHandler<M> + 'static,
{
fn handle(&self, req_enc: ReqEnc, from: NodeID) -> BoxFuture<Result<RespEnc, Error>> {
fn handle(&self, req_enc: ReqEnc, from: NodeID) -> BoxFuture<'_, Result<RespEnc, Error>> {
async move {
match self.0.handler.load_full() {
None => Err(Error::NoHandler),

View File

@@ -1,49 +1,49 @@
use std::io;
use err_derive::Error;
use log::error;
use thiserror::Error;
#[derive(Debug, Error)]
pub enum Error {
#[error(display = "IO error: {}", _0)]
Io(#[error(source)] io::Error),
#[error("IO error: {0}")]
Io(#[from] io::Error),
#[error(display = "Messagepack encode error: {}", _0)]
RMPEncode(#[error(source)] rmp_serde::encode::Error),
#[error(display = "Messagepack decode error: {}", _0)]
RMPDecode(#[error(source)] rmp_serde::decode::Error),
#[error("Messagepack encode error: {0}")]
RMPEncode(#[from] rmp_serde::encode::Error),
#[error("Messagepack decode error: {0}")]
RMPDecode(#[from] rmp_serde::decode::Error),
#[error(display = "Tokio join error: {}", _0)]
TokioJoin(#[error(source)] tokio::task::JoinError),
#[error("Tokio join error: {0}")]
TokioJoin(#[from] tokio::task::JoinError),
#[error(display = "oneshot receive error: {}", _0)]
OneshotRecv(#[error(source)] tokio::sync::oneshot::error::RecvError),
#[error("oneshot receive error: {0}")]
OneshotRecv(#[from] tokio::sync::oneshot::error::RecvError),
#[error(display = "Handshake error: {}", _0)]
Handshake(#[error(source)] kuska_handshake::async_std::Error),
#[error("Handshake error: {0}")]
Handshake(#[from] kuska_handshake::async_std::Error),
#[error(display = "UTF8 error: {}", _0)]
UTF8(#[error(source)] std::string::FromUtf8Error),
#[error("UTF8 error: {0}")]
UTF8(#[from] std::string::FromUtf8Error),
#[error(display = "Framing protocol error")]
#[error("Framing protocol error")]
Framing,
#[error(display = "Remote error ({:?}): {}", _0, _1)]
#[error("Remote error ({0:?}): {1}")]
Remote(io::ErrorKind, String),
#[error(display = "Request ID collision")]
#[error("Request ID collision")]
IdCollision,
#[error(display = "{}", _0)]
#[error("{0}")]
Message(String),
#[error(display = "No handler / shutting down")]
#[error("No handler / shutting down")]
NoHandler,
#[error(display = "Connection closed")]
#[error("Connection closed")]
ConnectionClosed,
#[error(display = "Version mismatch: {}", _0)]
#[error("Version mismatch: {0}")]
VersionMismatch(String),
}

View File

@@ -33,7 +33,7 @@ async-trait.workspace = true
serde.workspace = true
serde_bytes.workspace = true
serde_json.workspace = true
err-derive = { workspace = true, optional = true }
thiserror = { workspace = true, optional = true }
# newer version requires rust edition 2021
kube = { workspace = true, optional = true }
@@ -49,5 +49,5 @@ opentelemetry.workspace = true
[features]
kubernetes-discovery = [ "kube", "k8s-openapi", "schemars" ]
consul-discovery = [ "reqwest", "err-derive" ]
consul-discovery = [ "reqwest", "thiserror" ]
system-libs = [ "sodiumoxide/use-pkg-config" ]

View File

@@ -3,8 +3,8 @@ use std::fs::File;
use std::io::Read;
use std::net::{IpAddr, SocketAddr};
use err_derive::Error;
use serde::{Deserialize, Serialize};
use thiserror::Error;
use garage_net::NodeID;
@@ -219,12 +219,12 @@ impl ConsulDiscovery {
/// Regroup all Consul discovery errors
#[derive(Debug, Error)]
pub enum ConsulError {
#[error(display = "IO error: {}", _0)]
Io(#[error(source)] std::io::Error),
#[error(display = "HTTP error: {}", _0)]
Reqwest(#[error(source)] reqwest::Error),
#[error(display = "Invalid Consul TLS configuration")]
#[error("IO error: {0}")]
Io(#[from] std::io::Error),
#[error("HTTP error: {0}")]
Reqwest(#[from] reqwest::Error),
#[error("Invalid Consul TLS configuration")]
InvalidTLSConfig,
#[error(display = "Token error: {}", _0)]
Token(#[error(source)] reqwest::header::InvalidHeaderValue),
#[error("Token error: {0}")]
Token(#[from] reqwest::header::InvalidHeaderValue),
}

View File

@@ -21,7 +21,7 @@ arc-swap.workspace = true
async-trait.workspace = true
blake2.workspace = true
bytesize.workspace = true
err-derive.workspace = true
thiserror.workspace = true
hexdump.workspace = true
xxhash-rust.workspace = true
hex.workspace = true

View File

@@ -2,7 +2,7 @@
use std::fmt;
use std::io;
use err_derive::Error;
use thiserror::Error;
use serde::{de::Visitor, Deserialize, Deserializer, Serialize, Serializer};
@@ -12,71 +12,64 @@ use crate::encode::debug_serialize;
/// Regroup all Garage errors
#[derive(Debug, Error)]
pub enum Error {
#[error(display = "IO error: {}", _0)]
Io(#[error(source)] io::Error),
#[error("IO error: {0}")]
Io(#[from] io::Error),
#[error(display = "Hyper error: {}", _0)]
Hyper(#[error(source)] hyper::Error),
#[error("Hyper error: {0}")]
Hyper(#[from] hyper::Error),
#[error(display = "HTTP error: {}", _0)]
Http(#[error(source)] http::Error),
#[error("HTTP error: {0}")]
Http(#[from] http::Error),
#[error(display = "Invalid HTTP header value: {}", _0)]
HttpHeader(#[error(source)] http::header::ToStrError),
#[error("Invalid HTTP header value: {0}")]
HttpHeader(#[from] http::header::ToStrError),
#[error(display = "Network error: {}", _0)]
Net(#[error(source)] garage_net::error::Error),
#[error("Network error: {0}")]
Net(#[from] garage_net::error::Error),
#[error(display = "DB error: {}", _0)]
Db(#[error(source)] garage_db::Error),
#[error("DB error: {0}")]
Db(#[from] garage_db::Error),
#[error(display = "Messagepack encode error: {}", _0)]
RmpEncode(#[error(source)] rmp_serde::encode::Error),
#[error(display = "Messagepack decode error: {}", _0)]
RmpDecode(#[error(source)] rmp_serde::decode::Error),
#[error(display = "JSON error: {}", _0)]
Json(#[error(source)] serde_json::error::Error),
#[error(display = "TOML decode error: {}", _0)]
TomlDecode(#[error(source)] toml::de::Error),
#[error("Messagepack encode error: {0}")]
RmpEncode(#[from] rmp_serde::encode::Error),
#[error("Messagepack decode error: {0}")]
RmpDecode(#[from] rmp_serde::decode::Error),
#[error("JSON error: {0}")]
Json(#[from] serde_json::error::Error),
#[error("TOML decode error: {0}")]
TomlDecode(#[from] toml::de::Error),
#[error(display = "Tokio join error: {}", _0)]
TokioJoin(#[error(source)] tokio::task::JoinError),
#[error("Tokio join error: {0}")]
TokioJoin(#[from] tokio::task::JoinError),
#[error(display = "Tokio semaphore acquire error: {}", _0)]
TokioSemAcquire(#[error(source)] tokio::sync::AcquireError),
#[error("Tokio semaphore acquire error: {0}")]
TokioSemAcquire(#[from] tokio::sync::AcquireError),
#[error(display = "Tokio broadcast receive error: {}", _0)]
TokioBcastRecv(#[error(source)] tokio::sync::broadcast::error::RecvError),
#[error("Tokio broadcast receive error: {0}")]
TokioBcastRecv(#[from] tokio::sync::broadcast::error::RecvError),
#[error(display = "Remote error: {}", _0)]
#[error("Remote error: {0}")]
RemoteError(String),
#[error(display = "Timeout")]
#[error("Timeout")]
Timeout,
#[error(display = "Layout not ready")]
#[error("Layout not ready")]
LayoutNotReady,
#[error(
display = "Could not reach quorum of {} (sets={:?}). {} of {} request succeeded, others returned errors: {:?}",
_0,
_1,
_2,
_3,
_4
)]
#[error("Could not reach quorum of {0} (sets={1:?}). {2} of {3} request succeeded, others returned errors: {4:?}")]
Quorum(usize, Option<usize>, usize, usize, Vec<String>),
#[error(display = "Unexpected RPC message: {}", _0)]
#[error("Unexpected RPC message: {0}")]
UnexpectedRpcMessage(String),
#[error(display = "Corrupt data: does not match hash {:?}", _0)]
#[error("Corrupt data: does not match hash {0:?}")]
CorruptData(Hash),
#[error(display = "Missing block {:?}: no node returned a valid block", _0)]
#[error("Missing block {0:?}: no node returned a valid block")]
MissingBlock(Hash),
#[error(display = "{}", _0)]
#[error("{0}")]
Message(String),
}

View File

@@ -20,7 +20,7 @@ garage_model.workspace = true
garage_util.workspace = true
garage_table.workspace = true
err-derive.workspace = true
thiserror.workspace = true
tracing.workspace = true
percent-encoding.workspace = true

View File

@@ -1,6 +1,6 @@
use err_derive::Error;
use hyper::header::HeaderValue;
use hyper::{HeaderMap, StatusCode};
use thiserror::Error;
use garage_api_common::generic_server::ApiError;
@@ -8,15 +8,15 @@ use garage_api_common::generic_server::ApiError;
#[derive(Debug, Error)]
pub enum Error {
/// An error received from the API crate
#[error(display = "API error: {}", _0)]
#[error("API error: {0}")]
ApiError(garage_api_s3::error::Error),
/// The file does not exist
#[error(display = "Not found")]
#[error("Not found")]
NotFound,
/// The client sent a request without host, or with unsupported method
#[error(display = "Bad request: {}", _0)]
#[error("Bad request: {0}")]
BadRequest(String),
}