Throw Error.reject equivalent

What’s the equivalent in Rust of a throw Error.reject in Motoko? panic!?

e.g. a Motoko actor

public shared ({caller}) func delete(key : Text, data : DelData) : async () {
    if (Utils.isPrincipalNotEqual(caller, user)) {
      throw Error.reject("User does not have the permission to delete the data.");
    };

    let result : Result.Result<?Data, Text> = store.del(key, data);

    switch (result) {
      case (#err error) {
        throw Error.reject(error);
      };
      case (#ok resultData) {};
    };
  };

I prefer to have my functions return a Result and then use ?, match, or things like .and_then in the function body.

Using this approach makes testing easier.

When eventually needing to create an unrecoverable error from a Result you can do:

value.expect("User does not have the permission to delete the data.".to_string());

or

value.expect(format!("User {:#?} does not have the permission to delete the data.", user));

which is similar to value.unwrap() but without the error message, or using match and then panic! for the Err case.

Worth mentioning that this is probably eagerly evaluated and a way around that is to do something like:

value.ok_or_else(|| format!("User {:#?} does not have the permission to delete the data.", user)).unwrap();

I for sure like to use Result internally within the canister too but for exposed functions I rather like to throw because the frontend can just wrap the call with a try / catch and does not have to process the result. Less verbose on the frontend side in my opinion but of course, mater of taste.

Maybe I should have added this too, I am migrating an existing canister. Therefore I would not like to change the existing declaration - which uses throw - because otherwise I’ll have to update the frontend too.

I used panic! so far but not sure it’s the exact conversion.

#[update]
async fn upload_chunk(chunk: Chunk) -> UploadChunk {
    // TODO: is caller === user

    let result = create_chunk(chunk);

    match result {
        Ok(chunk_id) => { UploadChunk { chunk_id } }
        Err(error) => panic!("{}", error)
    }
}
1 Like

In that case perhaps you want ic_cdk::api::trap

1 Like

Ah nice, will do that!


Notes:

  • I found this thread and this thread about trap

  • there is also a call::error according this thread

In my case, the way I coded the functions - for good and bad - both probably do the job.

Someone from the Motoko team can probably answer what happens to unhandled exceptions that are thrown if you wanted to try and do the same thing exactly in Rust.

I most probably gonna discover that quickly when I’ll run the first tests :wink:.

Thanks for the quick answer.