# Rust CDK - How to catch panic/trap when calling another canister which traps?

**URL:** <https://forum.dfinity.org/t/rust-cdk-how-to-catch-panic-trap-when-calling-another-canister-which-traps/7886>\
**Category:** Developers\
**Created:** [October 13, 2021, 7:30pm UTC](https://forum.dfinity.org/t/rust-cdk-how-to-catch-panic-trap-when-calling-another-canister-which-traps/7886 "2021-10-13T19:30:16Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![shalexbas](https://sea1.discourse-cdn.com/flex023/user_avatar/forum.dfinity.org/shalexbas/32/2139_2.png) [@shalexbas](https://forum.dfinity.org/u/shalexbas)\
**Post date:** [October 13, 2021, 7:30pm UTC](https://forum.dfinity.org/t/rust-cdk-how-to-catch-panic-trap-when-calling-another-canister-which-traps/7886/1 "2021-10-13T19:30:17Z")

</div>

Hey,

I just want to know if it is possible to catch a panic/trap produced by calling another canister which traps (in Motoko it should be possible with a try-catch).  
I tried out **catch\_unwind** but my caller canister still traps.

Here is the panic message:  
_[Canister r7inp-6aaaa-aaaaa-aaabq-cai] Panicked at 'called `Result::unwrap()` on an `Err` value: (  
CanisterError, "IC0503: Canister ryjl3-tyaaa-aaaaa-aaaba-cai trapped explicitly: assertion failed_

Here is the code:

```auto
use futures::FutureExt;

#[import(
        candid_path = ".dfx/local/canisters/counter/counter.did",
        canister_id = "ryjl3-tyaaa-aaaaa-aaaba-cai"
    )]
    pub struct CounterCanister;

let result: std::result::Result<
            (ic_cdk::export::candid::Nat,),
            std::boxed::Box<dyn std::any::Any + std::marker::Send>,
        > = CounterCanister::increment().catch_unwind().await;

```

I think the generated code (CounterCanister) calls the following method in ic\_cdk:

```auto
pub async fn call<T: ArgumentEncoder, R: for<'a> ArgumentDecoder<'a>>(
    id: Principal,
    method: &str,
    args: T,
) -> CallResult<R> {
    let args_raw = encode_args(args).expect("Failed to encode arguments.");
    let bytes = call_raw(id, method, args_raw, 0).await?;
    decode_args(&bytes).map_err(|err| trap(&format!("{:?}", err)))
}

```

So on error trap function is called. Is it why I can’t catch the panic with _catch\_unwind()_? How to catch the panic then?

Thanks

---

<div class="post-metadata">

**Author:** ![Maxfinity](https://sea1.discourse-cdn.com/flex023/user_avatar/forum.dfinity.org/maxfinity/32/1484_2.png) [@Maxfinity](https://forum.dfinity.org/u/Maxfinity)\
**Post date:** [October 13, 2021, 11:21pm UTC](https://forum.dfinity.org/t/rust-cdk-how-to-catch-panic-trap-when-calling-another-canister-which-traps/7886/2 "2021-10-13T23:21:06Z")

</div>

It should be possible to catch the error if another canister is calling into the trapping canister. The trapping canister should return an error type to the outer canister.

So just pattern match the error rather than catch unwind.

---

<div class="post-metadata">

**Author:** ![rckprtr](https://sea1.discourse-cdn.com/flex023/user_avatar/forum.dfinity.org/rckprtr/32/809_2.png) [@rckprtr](https://forum.dfinity.org/u/rckprtr)\
**Post date:** [October 14, 2021, 12:49am UTC](https://forum.dfinity.org/t/rust-cdk-how-to-catch-panic-trap-when-calling-another-canister-which-traps/7886/3 "2021-10-14T00:49:06Z")

</div>

I asked a similar question before and it does not appear its possible to catch this error:

Here is my code:

> <https://github.com/dscvr-one/ic-drip/blob/better-props/src/ic_loot_rs/lib.rs#L540>

---

<div class="post-metadata">

**Author:** ![shalexbas](https://sea1.discourse-cdn.com/flex023/user_avatar/forum.dfinity.org/shalexbas/32/2139_2.png) [@shalexbas](https://forum.dfinity.org/u/shalexbas)\
**Post date:** [October 14, 2021, 7:22am UTC](https://forum.dfinity.org/t/rust-cdk-how-to-catch-panic-trap-when-calling-another-canister-which-traps/7886/4 "2021-10-14T07:22:38Z")

</div>

I don’t know how to pattern match it because the generated code (with _import_ macro from _ic-cdk-macros_) doesn’t produce any error result when calling. If I call the other canister like `CounterCanister::increment().await`, the compiler says that the result is a tupel `(ic_cdk::export::candid::Nat,)`, so there is nothing I can pattern match

---

<div class="post-metadata">

**Author:** ![shalexbas](https://sea1.discourse-cdn.com/flex023/user_avatar/forum.dfinity.org/shalexbas/32/2139_2.png) [@shalexbas](https://forum.dfinity.org/u/shalexbas)\
**Post date:** [October 14, 2021, 7:43am UTC](https://forum.dfinity.org/t/rust-cdk-how-to-catch-panic-trap-when-calling-another-canister-which-traps/7886/5 "2021-10-14T07:43:15Z")

</div>

It looks like this is the code that produce the generated code (ic-cdk-macros-0.3.2\src\import.rs):

```auto
fn actor_function_body(
        &self,
        name: &str,
        arguments: &[(String, String)],
        _returns: &str,
        _is_query: bool,
    ) -> Result<String, candid::error::Error> {
      ...

        let call = "ic_cdk::call";

        // We check the validity of the canister_id early so it fails if the
        // ID isn't in the right text format.
        let principal: ic_cdk::export::Principal =
            ic_cdk::export::Principal::from_text(canister_id).unwrap();

        Ok(format!(
            r#"
            {{
                {call}(
                  ic_cdk::export::Principal::from_text("{principal}").unwrap() as ic_cdk::export::Principal,
                  "{name}",
                  {arguments}
                 )
                 .await
                 .unwrap()
            }}
        "#,
            call = call,
            principal = &principal.to_text(),
            name = name.escape_debug(),
            arguments = arguments,
        ))
    }

```

It directly calls `await.unwrap()`…

---

<div class="post-metadata">

**Author:** ![shalexbas](https://sea1.discourse-cdn.com/flex023/user_avatar/forum.dfinity.org/shalexbas/32/2139_2.png) [@shalexbas](https://forum.dfinity.org/u/shalexbas)\
**Post date:** [October 14, 2021, 7:56am UTC](https://forum.dfinity.org/t/rust-cdk-how-to-catch-panic-trap-when-calling-another-canister-which-traps/7886/6 "2021-10-14T07:56:05Z")

</div>

I can catch the error with

```auto
let principal =
            ic_cdk::export::Principal::from_text("ryjl3-tyaaa-aaaaa-aaaba-cai").unwrap();
let result = ic_cdk::api::call::call(principal, "increment()", ()).await
            as CallResult<(ic_cdk::export::candid::Nat,)>;

if result.is_ok() {
           ...
        } else {
           ...
        }

```

Unfortunately it just works with _call()_ function but not with the **import** macro where the candid-file can be utilized
