DynamoDB documentClient.transactWrite throws ValidationException, but the datatype is correct

15 views Asked by At

I rewrote some code to take advantage of the transaction API. When I try to update an object containing product information I get the following error:

ValidationException: ExpressionAttributeValues contains invalid value: The parameter cannot be converted to a numeric value: NaN for key :products

It is correct that :products is NaN, it has the following typescript type: {productId:number, price:number}[] and that is the same type currently present in the database. I get the object from DDB, then only change the order, delete some elements, change some prices and write an object of the same type back.

I am using the TypeScript SDK.

This is the relevant part of the code:

const PRODUCTS_STATE_OBJECT_TYPE = "Products" as const;

type Product = { id: number; price: number };

type ProductsState = {
    objectType: typeof PRODUCTS_STATE_OBJECT_TYPE;
    objectIndex: number;
    lastUpdate: string;
    products: Array<Product>;
}

const client = new DocumentClient({ convertEmptyValues: true });

const productsQueryResult = await client
    .query({
      TableName: TABLE_NAME!,
      KeyConditionExpression: `objectType = :objectType`,
      ExpressionAttributeValues: {
        ":objectType": PRODUCTS_STATE_OBJECT_TYPE,
      },
    })
    .promise();

const productsArray:Array<Array<Product>> = ((productsQueryResult.Items ?? []) as Array<ProductsState>).map(({products})=>products)

// a bunch of code where I change productsArray to newProductsArray of the same type

const newProductsStates: Array<ProductsState> = newProductsArrays.map((products, objectIndex) => ({
    objectType: PRODUCTS_STATE_OBJECT_TYPE,
    objectIndex,
    lastUpdate: getCurrentDateString(),
    products,
  }));

const newProductsStatesRequestObjects: DocumentClient.TransactWriteItemList =
    newProductsStates.map(
      ({ objectIndex, objectType, lastUpdate, products }) => ({
        Update: {
          TableName: TABLE_NAME!,
          Key: { objectType, objectIndex },
          UpdateExpression:
            "set " +
            ["lastUpdate = :lastUpdate", "products = :products"].join(","),
          ExpressionAttributeValues: {
            ":lastUpdate": lastUpdate,
            ":products": products,
          },
        },
      })
    );

await client
    .transactWrite({
      TransactItems: [
        ...newProductsStatesRequestObjects,
      ],
    })
    .promise();

products is not supposed to be a number and I haven't defined any validation. It's also the same datatype as the object already in the database which I try to update.

This is the full error message:

ValidationException: ExpressionAttributeValues contains invalid value: The parameter cannot be converted to a numeric value: NaN for key :products
    at Request.extractError (/var/task/index.js:316:32)
    at Request.callListeners (/var/task/index.js:3336:24)
    at Request.emit (/var/task/index.js:3311:14)
    at Request.emit (/var/task/index.js:8496:18)
    at Request.transition (/var/task/index.js:8099:15)
    at AcceptorStateMachine.runTo (/var/task/index.js:6537:16)
    at /var/task/index.js:6552:15
    at Request.<anonymous> (/var/task/index.js:8115:13)
    at Request.<anonymous> (/var/task/index.js:8499:16)
    at Request.callListeners (/var/task/index.js:3346:22) {
  code: 'ValidationException',
  '[__type]': 'See error.__type for details.',
  time: 2024-03-07T02:36:33.519Z,
  requestId: '9IACI23LBETVAHCVSKDT28EBV7VV4KQNSO5AEMVJF66Q9ASUAAJG',
  statusCode: 400,
  retryable: false,
  retryDelay: 1.4080887836606215
}

I double checked that the object has the correct type by using console log.

0

There are 0 answers