Why getting "failed due to a missing authorization from 'Bob'"?

Here is my Token template in Token.daml:

module Token where

{-
  • Party can issue tokens
  • Party can transfer issued tokens to another Party
-}

type TokenId = ContractId Token

template Token
  with
    owner: Party
    tokenType: Text
    value: Int
  where
    signatory owner

    controller owner can
      nonconsuming TransferToken: TokenId
        with
          newOwner : Party
          numUnits: Int
        do
          create Token with
            owner = newOwner
            value = numUnits
            ..

And my Main.daml:

module Main where

import Token
import Daml.Script

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

  alice_token1_5 <- submit alice do
    createCmd Token with
      owner = alice
      tokenType = "token1"
      value = 5

  alice_token2_5 <- submit alice do
    createCmd Token with
      owner = alice
      tokenType = "token2"
      value = 5

  bob_token1_3 <- submit alice do
    exerciseCmd alice_token1_5 TransferToken
      with
        newOwner = bob
        numUnits = 3

  return ()

I’m getting the error- Scenario execution failed on commit at Main:23:19:
1: create of Token:Token at DA.Internal.Prelude:373:26
failed due to a missing authorization from ‘Bob’
Here is the complete error trace:

Scenario execution failed on commit at Main:23:19:
  1: create of Token:Token at DA.Internal.Prelude:373:26
     failed due to a missing authorization from 'Bob'

Ledger time: 1970-01-01T00:00:00Z

Partial transaction:
  Failed exercise (DA.Internal.Prelude:373:26):
    exercise TransferToken on #0:0 (Token:Token)
    with
      newOwner = 'Bob'; numUnits = 3
  Sub-transactions:
     1
     └─> create Token:Token
         with
           owner = 'Bob'; tokenType = "token1"; value = 3

Committed transactions: 
  TX 0 1970-01-01T00:00:00Z (Main:11:21)
  #0:0
  │   known to (since): 'Alice' (0)
  └─> create Token:Token
      with
        owner = 'Alice'; tokenType = "token1"; value = 5
  
  TX 1 1970-01-01T00:00:00Z (Main:17:21)
  #1:0
  │   known to (since): 'Alice' (1)
  └─> create Token:Token
      with
        owner = 'Alice'; tokenType = "token2"; value = 5

What is the error & how can I resolve it? I’m new to DAML & will highly appreciate any help on this.

In Token, you have declared that signatory owner. In the scope of TransferToken as exercised by alice, who is providing signatures? alice and only alice. Contracts created in the scope of a choice have the authorization of the controller, the signatories, and no one else. So bob is not on hand to supply their signature. That’s what the error

means.

You can take a look at choice Iou_Transfer and template IouTransfer in one of our quickstart examples for an example of the offer-acceptance pattern, which shows how you solve the conceptual problem that, in practice, you want two separate parties (the old owner and the new owner) to authorize a transfer at separate times.

Alternatively, any fair, transferrable representation of an asset will contain some elaboration of that pattern, so if you have an example application you’re referring to already, even odds it contains at least one of these.

Hi @Stephen if Bob’s authorisation is required then how is the below code working without any errors?
As can be seen below Bob is neither the issuer nor the owner when Alice exercises the Give choice. Infact here Alice is both the issuer & owner.

module Main where

import Daml.Script
type AssetId = ContractId Asset

template Asset
  with
    issuer : Party
    owner  : Party
    name   : Text
  where
    ensure name /= ""
    signatory issuer
    controller owner can
      Give : AssetId
        with
          newOwner : Party
        do
          create this with
            owner = newOwner

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

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

  bobTV <- submit alice do
    exerciseCmd aliceTV Give with newOwner = bob

  return ()

In that example Asset only has the issuer as the signatory not the owner. So the authorization from the new owner is not required when transferring. In your example, the owner is a signatory so their authorization is required.