Are intercanister calls safe?

I have two canisters, one calls another.

Both have enough free memory (both main one and stable one), and do some computations that normally don’t lead to exceptional conditions (e.g. they don’t divide by zero).

Can an intercanister call fail? If yes, what may be the reasons of the failure?

1 Like

Canister calls may fail,. yes.

The IC guarantees response delivery (whether it’s a response produced by the canister or by the System API if the canister traps). It obviously cannot guarantee how long it is going to take to deliver that response, but it will get delivered eventually.

But there are no delivery guarantees for requests. There may be any number of reasons for failing to deliver a request (out of cycles, full canister queue, timeout while the request is waiting to be routed, some canister or subnet memory limit being reached, etc.). The vast majority of time (unless you have hundreds of outstanding calls between the pair of canisters) requests are going to be delivered. But, as opposed to responses, there is no 100% delivery guarantee.

Speaking of which, the sender is guaranteed to get a response that accurately reflects what has happened to the request it sent. If the request was delivered and handled and a response produced, then that’s the response it is going to receive. If the request was delivered but the receiver trapped while executing it, that is also reflected in the response. Same as if the request was never delivered successfully. In the two latter cases you’d get back a reject response; in the former, a regular canister response.


Oh, also note that because response delivery guarantees impose some pretty significant limitations (e.g. you cannot upgrade a canister while it is awaiting a response) we are considering introducing a new class of messages that do not have response delivery guarantees. They would e.g. allow you to set a timeout (something quite essential for an interactive app, you don’t want to click a button and have to wait indefinitely for a response). If that timeout is exceeded you would get back a “timeout exceeded” response, and you obviously wouldn’t be able to tell based only on that response whether the request had been delivered, executed, rejected, etc.

This is just an idea at this point though. And you would need to opt into this behavior, so if you write a canister today, it is and it will forever be guaranteed to get accurate responses to every request that it sends out.