DynamoDB TransactWrite fails, but throws no error

0

I am writing a function to move three related items from their table to another using DynamoDB Transaction. I am writing the code in TypeScript with the SDK version 2.991.0 basically following this example code from the documentation: https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/DynamoDB/DocumentClient.html#transactWrite-property

The Problem is that documentclient.transactWrite does terminate without throwing an error, it doesn't pass an error to the callback function and the response object also has no error. However, the whole transaction fails without performing the delete or put instructions.

I verified that all the item keys exist and that the lambda has all the necessary permissions, but even if the items didn't exist or the permissions were missing I'd expect an error to be thrown.

This is the relevant part of my code:

const {
  TABLE_NAME1,  TABLE_NAME2,  TABLE_NAME3,  TABLE_NAME4,  TABLE_NAME5,  TABLE_NAME6,  TABLE_NAME7,  TABLE_NAME8,
} = process.env

const getMoveItemInput = (
  fromTableName: string,
  toTableName: string,
  Key: Record<string, string | number>,
  Item: any
) => [
  { Delete: { TableName: fromTableName, Key } },
  {
    Put: {
      TableName: toTable,
      Item,
    },
  },
]

export const handler = async (event) => {
  const client = new DocumentClient({ convertEmptyValues: true })
  const { itemId, removeFromBill } = event.arguments

 /* Get userInfo, the item, orders and so on from DynamoDB + some verification
the following variables are read from the DB: itemBillingInfo, userId, item, orders, gifts
*/

  const transactionItemDeleteBillingInfo = {
    Delete: {
      TableName: TABLE_NAME2!,
      Key: {
        hashKey: itemBillingInfo?.hashKey,
        sortKey: itemBillingInfo?.sortKey,
      },
    },
  }

  const transactionItemMoveItem = getMoveItemInput(
    TABLE_NAME1!,
    TABLE_NAME6!,
    { userId, itemId },
    item
  )

  const transactionItemMoveOrders = orders.map((order) =>
    getMoveItemInput(
      TABLE_NAME5!,
      TABLE_NAME8!,
      { userId: order.userId, orderId: order.orderId },
      order
    )
  )

  const transactionItemMoveGifts = gifts.map((gift) =>
    getMoveItemInput(
      TABLE_NAME4!,
      TABLE_NAME7!,
      { userId: gift.userId, orderId: gift.orderId },
      giftOrder
    )
  )

  const transactionInput = {
    TransactItems: [
      ...transactionItemMoveItem,
      ...transactionItemMoveOrders.flat(),
      ...transactionItemMoveGifts.flat(),
      ...(removeFromBill && itemBillingInfo ? [transactionItemDeleteBillingInfo] : []),
    ],
  }

  console.log(JSON.stringify(transactionInput, null, 2))
  const response = client.transactWrite(transactionInput, (error) => {
    if (error) {
      console.log(error)
    }
  })
  console.log(response)
  return true
}

If there is no order associated with the item it works as intended, but I am looking for an answer as to why there is no error thrown and no error passed to the callback.

Thanks for reading.

asked 10 months ago695 views
1 Answer
0

Quite simply because you are using an async Lambda function but you don't await a response, so the Lambda container quits before you can see any exception. Be sure to add await to any of your API calls.

profile pictureAWS
EXPERT
answered 10 months ago
  • In the documentation it says "Synchronous write operation that groups up to 100 action requests." and the java docs comment form the node package is "Synchronous write operation that groups up to 25 action requests.". I tried const response = await client.transactWrite(...), but that also doesn't work (and my IDE also tells me that client.transactWrite is synchronous)

  • Its not clear which version of the SDK you use, as your client doesn't align with the proper import syntax. But I can make an assumption is V2, in which case you must await a promise. I suggest researching a little more on async/await programming with JS. Try await client.transactWrite(...).promise()

You are not logged in. Log in to post an answer.

A good answer clearly answers the question and provides constructive feedback and encourages professional growth in the question asker.

Guidelines for Answering Questions