Choice exercise error not caught by try-catch in Daml Script

I want to write a test in Daml Script which returns the error message returned by a failed choice exercise, but the error is not caught by the try-catch expression.

I would expect the test script below to succeed and return the error message as text, but it fails:

Script execution failed on commit at Main:49:5:
  Unhandled exception:  DA.Exception.AssertionFailed:AssertionFailed@3f4deaf145a15cdcfa762c058005e2edb9baa75bb7f95a4f8f6f937378e86415 with
                          message = "Cannot give Asset to yourself"

What am I doing wrong?

module Main where

import Daml.Script

type AssetId = ContractId Asset

template Asset
  with
    issuer : Party
    owner  : Party
    name   : Text
  where
    ensure name /= ""
    signatory issuer
    observer owner
    key owner : Party
    maintainer key
    choice Give : AssetId
      with
        newOwner : Party
      controller owner
      do 
        assertMsg "Cannot give Asset to yourself" $ newOwner /= owner
        create this with
            owner = newOwner

setup : Script (Party, ContractId Asset)
setup = script do
-- user_setup_begin
  alice <- allocatePartyWithHint "Alice" (PartyIdHint "Alice")
  bob <- allocatePartyWithHint "Bob" (PartyIdHint "Bob")
  aliceId <- validateUserId "alice"
  bobId <- validateUserId "bob"
  createUser (User aliceId (Some alice)) [CanActAs alice]
  createUser (User bobId (Some bob)) [CanActAs bob]
-- user_setup_end

  aliceTV <- submit alice do
    createCmd Asset with
      issuer = alice
      owner = alice
      name = "TV"

  return (alice, aliceTV)

testAssertion : (Party, ContractId Asset) -> Script Text
testAssertion (alice, cid) = do 
  try do
    submit alice $ exerciseCmd cid (Give alice)
    pure "Shouldn't happen"
  catch 
    (ex : AnyException) -> pure $ DA.Internal.Desugar.message ex

test : Script Text
test = setup >>= testAssertion

try/catch, which also has on-ledger-related semantics (persisting the rollback nodes of the transaction), is a bit of an odd feature in Daml Script, which is an off-ledger Daml runtime. Right now, this behavior is more or less expected and I don’t think there’s a plan to change this. If you want to test that something “successfully fails” you should use assertFail, as described in our documentation here as well.

1 Like

Thanks, I agree, try/catch doesn’t make much sense in this way in Daml Script.

The limitation of submitMustFail (or assertFail for that matter) is that it cannot extract the error message from the update, but it seems I have to make do with what we have.