You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

DynamoDB documentClient.transactWrite触发ValidationException,类型却正确

问题

重写代码使用DynamoDB事务API更新产品信息对象时,遇到以下错误:
ValidationException: ExpressionAttributeValues contains invalid value: The parameter cannot be converted to a numeric value: NaN for key :products

:products确实为NaN,它的TypeScript类型是{productId:number, price:number}[],和数据库中现有类型一致。从DDB获取对象后,仅修改元素顺序、删除部分元素、调整部分价格,再将同类型对象写回。

使用TypeScript SDK,相关代码如下:

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)

// 一堆修改productsArray为newProductsArray的代码,类型保持一致

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不是数值类型,也没定义校验规则,且和待更新的数据库对象类型一致。完整错误信息:

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
}

已通过console.log确认对象类型正确。

解决方案
  • 检查产品价格是否生成NaN:TypeScript类型定义是number不代表实际值不会出错,比如价格调整时的除以0、非数字字符串转数字操作都会生成NaN。在生成newProductsArrays后,遍历过滤或替换NaN值:
    // 示例:将NaN替换为0,也可根据业务逻辑抛出错误或使用默认值
    const sanitizedProducts = products.map(p => ({
      ...p,
      price: isNaN(p.price) ? 0 : p.price
    }));
    
  • 校验数组本身有效性:排查是否有错误赋值导致数组变成NaN的情况,在生成newProductsStates前添加校验:
    newProductsArrays.forEach((arr, index) => {
      if (!Array.isArray(arr)) {
        throw new Error(`索引${index}的products不是有效数组: ${arr}`);
      }
    });
    
  • 调整DocumentClient配置:当前开启了convertEmptyValues: true,可能在边缘场景下导致数组被异常转换,尝试移除该配置:
    const client = new DocumentClient();
    
  • 临时替换为Put操作排查:如果Update操作问题仍存在,用Put操作替换Update,确认是否是Update表达式的问题:
    // 替换原Update逻辑为Put
    newProductsStates.map((item) => ({
      Put: {
        TableName: TABLE_NAME!,
        Item: item
      }
    }))
    

内容的提问来源于stack exchange,提问作者MWHmann

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 09:14:53