When does the catch block of try catch run in motoko?

I’m still a little confused in what cases does the catch block run in terms of trying an inter-canister call.

Let’s say I have code:

public func someFunc() {

try {
let result = await otherActor.otherFunc();
}
catch e {
// perform some action if other canister traps
doSomethingInCatch();
};

}

When does the catch block run? In which of the following cases (if any) does it run:

  • Canister I call with “otherActor” traps.
  • Canister I call with “otherActor” rejects call for some reason (message queue limit, etc.)

Both.

But if the try block fails directly with a trap (not in some async callee) the catch will not be executed and the enclosing method will, instead, immediately exit with the trap. The caller of the method will see this as a reject.

Note that message sends can, in rare cases, trap synchronously, before the message body is even queued and executed, which falls into the case of the previous paragraph.

Hope I got that right. Not caffeinated yet.

4 Likes

Look at it this way: if any error happens for whatever reason in the try block, it should always go in the catch. At least that’s how a try / catch should work

That’s how it should work, but doesn’t.

try { 1/0 } catch { return 42; }

will not be caught. Unfortunately. But

try { await async {1/0} } catch { return 42; }

will.

So as Claudio says: It can only catch when the canister receives a reject from another canister, or (I believe) if you throw explicitly.

2 Likes