diff --git a/Cargo.lock b/Cargo.lock
index 58e18e9520244b32f38d1f008cd7061e63a5556f..8a925ab9a54f3ab31fbdedafd3c23997159842bd 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1166,6 +1166,7 @@ dependencies = [
  "bincode",
  "dubp",
  "serde",
+ "thiserror",
 ]
 
 [[package]]
diff --git a/rust-libs/modules/gva/bca/src/lib.rs b/rust-libs/modules/gva/bca/src/lib.rs
index b4928cee5a587eb1c7ef7845cc59d519d474cf52..e615dbd1135f8c9b4ee2075fd1a606baca4b846a 100644
--- a/rust-libs/modules/gva/bca/src/lib.rs
+++ b/rust-libs/modules/gva/bca/src/lib.rs
@@ -34,7 +34,7 @@ use async_bincode::AsyncBincodeReader;
 use bincode::Options as _;
 use dubp::crypto::keys::{ed25519::Ed25519KeyPair, Signator};
 use duniter_bca_types::{
-    bincode_opts, BcaReq, BcaReqTypeV0, BcaResp, BcaRespTypeV0, BcaRespV0, ReqExecError,
+    bincode_opts, BcaReq, BcaReqExecError, BcaReqTypeV0, BcaResp, BcaRespTypeV0, BcaRespV0,
 };
 use duniter_dbs::{FileBackend, SharedDbs};
 use futures::{prelude::stream::FuturesUnordered, StreamExt, TryStream, TryStreamExt};
@@ -146,11 +146,11 @@ impl BcaExecutor {
                         let resp = match req_res {
                             Ok(resp) => Ok(resp),
                             Err(e) => Err(if e.is_cancelled() {
-                                ReqExecError::Cancelled
+                                BcaReqExecError::Cancelled
                             } else if e.is_panic() {
-                                ReqExecError::Panic
+                                BcaReqExecError::Panic
                             } else {
-                                ReqExecError::Unknown
+                                BcaReqExecError::Unknown
                             }),
                         };
                         let mut resp_buffer = RespBytes::new();
@@ -163,8 +163,8 @@ impl BcaExecutor {
                     .await
             }
             Err(e) => {
-                let req_res: Result<BcaResp, ReqExecError> =
-                    Err(ReqExecError::InvalidReq(e.to_string()));
+                let req_res: Result<BcaResp, BcaReqExecError> =
+                    Err(BcaReqExecError::InvalidReq(e.to_string()));
                 let mut resp_buffer = RespBytes::new();
                 bincode_opts()
                     .serialize_into(&mut resp_buffer, &req_res)
@@ -294,8 +294,8 @@ mod tests {
         //println!("bytes={:?}", bytes);
         let bytes_res = bca_executor.execute::<&[u8]>(&bytes[..], false).await;
         //println!("bytes_res={:?}", bytes_res);
-        let bca_res: Vec<Result<BcaResp, ReqExecError>> =
-            AsyncBincodeReader::<_, Result<BcaResp, ReqExecError>>::from(&bytes_res[..])
+        let bca_res: Vec<Result<BcaResp, BcaReqExecError>> =
+            AsyncBincodeReader::<_, Result<BcaResp, BcaReqExecError>>::from(&bytes_res[..])
                 .try_collect::<Vec<_>>()
                 .await?;
 
@@ -332,14 +332,14 @@ mod tests {
         //println!("bytes={:?}", bytes);
         let bytes_res = bca_executor.execute::<&[u8]>(&bytes[..], false).await;
         //println!("bytes_res={:?}", bytes_res);
-        let bca_res: Vec<Result<BcaResp, ReqExecError>> =
-            AsyncBincodeReader::<_, Result<BcaResp, ReqExecError>>::from(&bytes_res[..])
+        let bca_res: Vec<Result<BcaResp, BcaReqExecError>> =
+            AsyncBincodeReader::<_, Result<BcaResp, BcaReqExecError>>::from(&bytes_res[..])
                 .try_collect::<Vec<_>>()
                 .await?;
 
         assert_eq!(
             bca_res,
-            vec![Err(ReqExecError::InvalidReq(
+            vec![Err(BcaReqExecError::InvalidReq(
                 "io error: unexpected end of file".to_owned()
             ))]
         );
@@ -376,8 +376,8 @@ mod tests {
         //println!("bytes={:?}", bytes);
         let bytes_res = bca_executor.execute::<&[u8]>(&bytes[..], false).await;
         //println!("bytes_res={:?}", bytes_res);
-        let bca_res: Vec<Result<BcaResp, ReqExecError>> =
-            AsyncBincodeReader::<_, Result<BcaResp, ReqExecError>>::from(&bytes_res[..])
+        let bca_res: Vec<Result<BcaResp, BcaReqExecError>> =
+            AsyncBincodeReader::<_, Result<BcaResp, BcaReqExecError>>::from(&bytes_res[..])
                 .try_collect::<Vec<_>>()
                 .await?;
 
diff --git a/rust-libs/modules/gva/bca/types/Cargo.toml b/rust-libs/modules/gva/bca/types/Cargo.toml
index 8c6c10bd956a333b9cd560140dff25c0403a7f0f..69634c022e0f1ced5d652e81e8b78dc1bb833fc0 100644
--- a/rust-libs/modules/gva/bca/types/Cargo.toml
+++ b/rust-libs/modules/gva/bca/types/Cargo.toml
@@ -9,6 +9,7 @@ edition = "2018"
 bincode = "1.3"
 dubp = { version = "0.49.0" }
 serde = { version = "1.0.105", features = ["derive"] }
+thiserror = "1.0.20"
 
 [features]
 default = ["duniter"]
diff --git a/rust-libs/modules/gva/bca/types/src/lib.rs b/rust-libs/modules/gva/bca/types/src/lib.rs
index 7b614366eb8f37aaf5da3a017921dd2b8df32934..fd00de4f3a4a8debda71f02fdc0b49dcc7b1aa3d 100644
--- a/rust-libs/modules/gva/bca/types/src/lib.rs
+++ b/rust-libs/modules/gva/bca/types/src/lib.rs
@@ -31,6 +31,7 @@ use dubp::crypto::hashs::Hash;
 use dubp::crypto::keys::ed25519::{PublicKey, Signature};
 use dubp::wallet::prelude::*;
 use serde::{Deserialize, Serialize};
+use thiserror::Error;
 
 pub fn bincode_opts() -> impl bincode::Options {
     bincode::options()
@@ -83,12 +84,16 @@ pub enum BcaRespTypeV0 {
     Pong,
 }
 
-pub type BcaResult = Vec<Result<BcaResp, ReqExecError>>;
+pub type BcaResult = Vec<Result<BcaResp, BcaReqExecError>>;
 
-#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize)]
-pub enum ReqExecError {
+#[derive(Clone, Debug, Deserialize, Error, PartialEq, Eq, Serialize)]
+pub enum BcaReqExecError {
+    #[error("task cancelled")]
     Cancelled,
+    #[error("Invalid request: {0}")]
     InvalidReq(String),
+    #[error("task panicked")]
     Panic,
+    #[error("Unknown error")]
     Unknown,
 }