Question about Message Guarantees

It cannot happen if the ledger doesn’t make any downstream calls of its own. If it does make downstream calls, then the following sequence of events (from the point of view of the ledger canister) is possible:

  1. Message 0 (request): ledger successfully mints the tokens and makes a downstream call (say to an archive canister), persisting the change.
  2. Message 1 (downstream response): ledger handles the downstream response, exceeds its memory limit (or the subnet’s memory limit; or instruction limit; or does a division by zero; or causes a stack overflow; or just traps), producing a reject response.

At this point, some or all of the requested operations (e.g. minting) have succeeded and been persisted; and the caller has received a reject response. It doesn’t even require a bug in the canister or replica, this is entirely expected behavior.

Messaging guarantees only work for single messages (one request / one response), not for calls (whole request handlers). And because an await may be hidden at the bottom of some library function, it’s not even straightforward to ensure that a specific request handler will execute atomically.

Looking at it from yet another perspective, the guarantees you get from a call or call tree are only as strong as the weakest response handler (which is not very strong, as the system may unilaterally trigger a trap / reject during the execution of any response message).