Got an error from "daml start" but not from daml studio's script result

Hello,

I am getting this error when I did “daml start …”

   ____             ____
  / __/__ ____  ___/ / /  ___ __ __
 _\ \/ _ `/ _ \/ _  / _ \/ _ \\ \ /
/___/\_,_/_//_/\_,_/_.__/\___/_\_\

INFO: Initialized sandbox version 1.8.0 with ledger-id = 7ed33b5b-b32b-4601-853c-6d2fb20c4c7f, port = 6865, dar file = List(.daml/dist/keplaax-1.0.0.dar), time mode = wall-clock time, ledger = in-memory, auth-service = AuthServiceWildcard$, contract ids seeding = strong
Running the initialization script.
Error: User abort: Pattern match failure in do expression at src/main/daml/Keplaax/LedgerSetupScript.daml:183:5-17
Exception in thread "main" com.daml.lf.speedy.SError$DamlEUserError
	at com.daml.lf.speedy.SBuiltin$SBError$.executePure(SBuiltin.scala:1372)
	at com.daml.lf.speedy.SBuiltinPure.execute(SBuiltin.scala:55)
	at com.daml.lf.speedy.Speedy$Machine.enterApplication(Speedy.scala:523)
	at com.daml.lf.speedy.SExpr$SEAppAtomicGeneral.execute(SExpr.scala:139)
	at com.daml.lf.speedy.Speedy$Machine.run(Speedy.scala:391)
	at com.daml.lf.engine.script.Runner.stepToValue$1(Runner.scala:386)
	at com.daml.lf.engine.script.Runner.com$daml$lf$engine$script$Runner$$run$1(Runner.scala:409)
	at com.daml.lf.engine.script.Runner$$anonfun$$nestedInanonfun$runWithClients$7$10.$anonfun$applyOrElse$66(Runner.scala:662)
	at scala.concurrent.Future.$anonfun$flatMap$1(Future.scala:307)
	at scala.concurrent.impl.Promise.$anonfun$transformWith$1(Promise.scala:41)
	at scala.concurrent.impl.CallbackRunnable.run(Promise.scala:64)
	at akka.dispatch.BatchingExecutor$AbstractBatch.processBatch(BatchingExecutor.scala:56)
	at akka.dispatch.BatchingExecutor$BlockableBatch.$anonfun$run$1(BatchingExecutor.scala:93)
	at scala.runtime.java8.JFunction0$mcV$sp.apply(JFunction0$mcV$sp.java:23)
	at scala.concurrent.BlockContext$.withBlockContext(BlockContext.scala:85)
	at akka.dispatch.BatchingExecutor$BlockableBatch.run(BatchingExecutor.scala:93)
	at akka.dispatch.TaskInvocation.run(AbstractDispatcher.scala:48)
	at akka.dispatch.ForkJoinExecutorConfigurator$AkkaForkJoinTask.exec(ForkJoinExecutorConfigurator.scala:48)
	at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:289)
	at java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1056)
	at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1692)
	at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:172)
daml-helper: Received ExitFailure 1 when running
Raw command: java -Dlogback.configurationFile=/Users/waichee/.daml/sdk/1.8.0/daml-sdk/script-logback.xml -jar /Users/waichee/.daml/sdk/1.8.0/daml-sdk/daml-sdk.jar script --dar .daml/dist/keplaax-1.0.0.dar --script-name Keplaax.LedgerSetupScript:initialize --wall-clock-time --ledger-host localhost --ledger-port 6865

But I didn’t get that from DAML studio. I meant, I can get to “Script results” and the script Keplaax.LedgerSetupScript:initialize was getting executed correctly.

I look at the code, nothing ring the bell (line 183 is queryContractKey …)

-- Test Reject
Some (cid, _) <- queryContractKey @AccountPayable directorUK (directorUK, directorCN)
pid <- submit directorUK do
    exerciseCmd cid CreatePurchaseOrderRequest with
        items=[item0]
        currency = RMB 
        settlementDate = (date 2020 Dec 9) 
        shippingAgreement = Some CIF
        deliveryDate = (date 2020 Dec 25)
        ..

Any idea?

1 Like

Hi @a14843,

A line like

do
    Some a <- expression

is a shorthand for:

do
    r <- expression
    let a = case r of
            Some n -> n
            None -> error "Pattern match failure"

It looks like you are hitting the (implicit) second branch here, i.e. when running the script “for real” queryContractKey returns None. It’s hard to say why that is without access to your entire init sequence.

Since it seems plausible, in general, to have your query not find anything, perhaps you should account for that explicitly and rewrite your code to something like:

do
    ...
    case queryContractKey @AccountPayable directorUK (directorUK, directorCN) of
        Some (cid, _) -> do
            exerciseCmd cid CreatePurchaseOrderRequest with ...
        None -> do
            -- what now?
2 Likes

Thanks for your reply over Xmas.

Here is the code that creates the contact from @AccountPayable:

cid <- submit directorUK do
    exerciseCmd uk_id AccountPayableInvitation_Send with
        recipient=directorCN
cn_billTo_uk <- submit directorCN do 
    exerciseCmd cid AccountPayableInvitiation_Accept

I did a bit more testing and found that queryFilter works, but not queryContractKey.

-- attempt 1
aps <- queryFilter @AccountPayable directorUK (\ap -> (ap.seller == directorCN))
pid <- case aps of
    (cid, _)::_ -> submit directorUK do
        exerciseCmd cid CreatePurchaseOrder with
            items=[item0,item1]
            ..
    [] -> abort ("no good contract 1")

-- attempt 2
aps <- queryContractKey @AccountPayable directorUK (directorUK, directorCN)
pid <- if isSome aps 
    then do 
        let (cid, _) = fromSome (aps)
        submit directorUK do
            exerciseCmd cid CreatePurchaseOrder with
                items=[item0,item1]
                ..
    else 
        abort ("no good contract 2")

I can get both of these queries to work in Daml studio, but “daml start” will throw an error on the second case.

INFO: Initialized sandbox version 1.8.0 with ledger-id = 3f2caa3b-a997-4f03-ab2d-aa169c57b0a3, port = 6865, dar file = List(.daml/dist/keplaax-1.0.0.dar), time mode = wall-clock time, ledger = in-memory, auth-service = AuthServiceWildcard$, contract ids seeding = strong
Error: User abort: no good contract 2
Exception in thread "main" com.daml.lf.speedy.SError$DamlEUserError
	at com.daml.lf.speedy.SBuiltin$SBError$.executePure(SBuiltin.scala:1372)
	at com.daml.lf.speedy.SBuiltinPure.execute(SBuiltin.scala:55)
	at com.daml.lf.speedy.Speedy$Machine.enterApplication(Speedy.scala:523)
	at com.daml.lf.speedy.SExpr$SEAppAtomicGeneral.execute(SExpr.scala:139)
	at com.daml.lf.speedy.Speedy$Machine.run(Speedy.scala:391)
	at com.daml.lf.engine.script.Runner.stepToValue$1(Runner.scala:386)
	at com.daml.lf.engine.script.Runner.com$daml$lf$engine$script$Runner$$run$1(Runner.scala:409)
	at com.daml.lf.engine.script.Runner$$anonfun$$nestedInanonfun$runWithClients$7$10.$anonfun$applyOrElse$66(Runner.scala:662)
	at scala.concurrent.Future.$anonfun$flatMap$1(Future.scala:307)
	at scala.concurrent.impl.Promise.$anonfun$transformWith$1(Promise.scala:41)
	at scala.concurrent.impl.CallbackRunnable.run(Promise.scala:64)
	at akka.dispatch.BatchingExecutor$AbstractBatch.processBatch(BatchingExecutor.scala:56)
	at akka.dispatch.BatchingExecutor$BlockableBatch.$anonfun$run$1(BatchingExecutor.scala:93)
	at scala.runtime.java8.JFunction0$mcV$sp.apply(JFunction0$mcV$sp.java:23)
	at scala.concurrent.BlockContext$.withBlockContext(BlockContext.scala:85)
	at akka.dispatch.BatchingExecutor$BlockableBatch.run(BatchingExecutor.scala:93)
	at akka.dispatch.TaskInvocation.run(AbstractDispatcher.scala:48)
	at akka.dispatch.ForkJoinExecutorConfigurator$AkkaForkJoinTask.exec(ForkJoinExecutorConfigurator.scala:48)
	at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:289)
	at java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1056)
	at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1692)
	at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:172)
daml-helper: Received ExitFailure 1 when running
Raw command: java -Dlogback.configurationFile=/Users/waichee/.daml/sdk/1.8.0/daml-sdk/script-logback.xml -jar /Users/waichee/.daml/sdk/1.8.0/daml-sdk/daml-sdk.jar script --dar .daml/dist/keplaax-1.0.0.dar --script-name Keplaax.LedgerSetupScript:initialize --wall-clock-time --ledger-host localhost --ledger-port 6865
1 Like

I’m afraid I will not be able to help you further. My knowledge in this area is actually fairly limited; this looks like a bug in the DAML toolset to me, but I don’t know enough to be sure.

In case anyone else wants to take a look at this (@cocreature or @Andreas, perhaps?), here is the smallest reproduction I could come up with:

daml.yaml:

sdk-version: 1.8.0
name: t
source: daml
init-script: Main:setup
parties:
  - Alice
  - Bob
version: 0.0.1
dependencies:
  - daml-prim
  - daml-stdlib
  - daml-script
sandbox-options:
  - --wall-clock-time

daml/Main.daml:

module Main where

import Daml.Script

template Asset
  with
    issuer : Party
    owner : Party
  where
    signatory issuer
    key (issuer, owner) : (Party, Party)
    maintainer key._1

setup : Script ()
setup = script do
  alice <- allocatePartyWithHint "Alice" (PartyIdHint "Alice")

  aliceTV <- submit alice do
    createCmd Asset with
      issuer = alice
      owner = alice
  c <- queryContractKey @Asset alice (alice, alice)
  case c of
    Some _ -> debug "seems to work"
    None -> abort "not found"
  return ()

This reliably works in DAML Studio, producing the expected trace “seems to work”, while daml start reliably fails and prints “not found”.

Interestingly, this works reliably for both daml start and DAML Studio:

module Main where

import Daml.Script

template Asset
  with
    issuer : Party
  where
    signatory issuer
    key issuer: Party
    maintainer key

setup : Script ()
setup = script do
  alice <- allocatePartyWithHint "Alice" (PartyIdHint "Alice")

  aliceTV <- submit alice do
    createCmd Asset with
      issuer = alice
  c <- queryContractKey @Asset alice alice
  case c of
    Some _ -> debug "seems to work"
    None -> abort "not found"
  return ()

where the key is now a single party, rather than a tuple.

1 Like

Agree that it smells like a bug. I will wait for update from the experts.

1 Like

I should mention that our offices are officially closed until Jan 1, so you may have to wait up until Jan 4 to get an answer.

1 Like

No problem, as I can workaround the problem by hardcoding the contractId for now.

1 Like

Hi @a14843, this was a bug in DAML Script when running against the gRPC Ledger API. We just merged a fix which will be included in this week’s snapshot and the next stable release 1.9.

2 Likes