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

Express.js + DynamoDB遇ValidationException:键元素与Schema不匹配

解决DynamoDB GetCommand的ValidationException错误

问题背景

使用JavaScript v3 SDK的DynamoDBClient + Express.js开发后端,调用GetCommand时触发以下错误:

Error: ValidationException: The provided key element does not match the schema
    at throwDefaultError (...)
    ...
    __type: 'com.amazon.coral.validate#ValidationException'

已完成排查:

  • AWS凭证有效,React应用可正常使用
  • ScanCommand能成功拉取DynamoDB数据到前端
  • 前端数据可正常传递至后端

后端核心代码:

import Express from "express";
import cors from "cors";
import dotenv from "dotenv";
import path from "path";
import bodyparser from "body-parser";
import {DynamoDBClient} from "@aws-sdk/client-dynamodb";
import {GetCommand} from "@aws-sdk/lib-dynamodb"; // 文档客户端的GetCommand
import {fromEnv} from "@aws-sdk/credential-providers";
import bcrypt from 'bcrypt';

const aws_creds = path.join(process.cwd(), "../", "env/", "awsbackend.env")
console.log("ENV File: " + aws_creds.toString());

dotenv.config({path: aws_creds});

console.log(process.env.backendport);
console.log(process.env.AWS_ACCESS_KEY_ID);

var capstone_proj = Express();

capstone_proj.use(cors());
capstone_proj.use(bodyparser.json());

var creds = fromEnv();
let DBnoSQL = new DynamoDBClient({
  region: process.env.region,
  credentials: creds,
});

capstone_proj.post('/login', async (req, res) => {
  const { Usrname, Password } = req.body;

  console.log(req.body);

  try {
    const command = new GetCommand({
      TableName: "Users",
      Key : {
         "Username": {S: Usrname} // 这里用了低级API的类型标识格式
      }
    });
    const data = await DBnoSQL.send(command);

    if (!data.Item) {
      return res.status(404).json({ error: 'Wrong login credentials' });
    }

    const isPasswordValid = await bcrypt.compare(
      Password,
      data.Item.Password_Hash.S, // 同样用了低级API的字段读取方式
    );

    if (isPasswordValid) {
      return res.status(200).json({ message: "Login successful" });
    } else {
      return res.status(401).json({ message: "Wrong login credentials" });
    }
  } catch (error) {
    console.error("Error:", error);
    return res.status(500).json({ message: "Internal server error" });
  }
});

capstone_proj.listen(process.env.backendport, () => {
    console.log("Backend listening on " + process.env.backendport)
})

错误原因

混用了DynamoDB低级客户端和文档客户端的API格式:

  • 导入的GetCommand来自@aws-sdk/lib-dynamodb(文档客户端),它支持直接使用原生JavaScript类型(字符串、数字等),不需要指定S(字符串)、N(数字)这类DynamoDB类型标识
  • 但在Key和读取Item字段时,用了低级客户端(@aws-sdk/client-dynamodb)的格式,导致请求格式与表的键schema不匹配,触发ValidationException

修复方案

修改代码中GetCommand的Key格式,以及后续读取Item字段的方式,统一使用文档客户端的原生JS类型格式:

capstone_proj.post('/login', async (req, res) => {
  const { Usrname, Password } = req.body;

  console.log(req.body);

  try {
    const command = new GetCommand({
      TableName: "Users",
      Key : {
         "Username": Usrname // 去掉{S: ...},直接传原生字符串
      }
    });
    const data = await DBnoSQL.send(command);

    if (!data.Item) {
      return res.status(404).json({ error: 'Wrong login credentials' });
    }

    // 直接读取字段值,不需要.S后缀
    const isPasswordValid = await bcrypt.compare(
      Password,
      data.Item.Password_Hash,
    );

    if (isPasswordValid) {
      return res.status(200).json({ message: "Login successful" });
    } else {
      return res.status(401).json({ message: "Wrong login credentials" });
    }
  } catch (error) {
    console.error("Error:", error);
    return res.status(500).json({ message: "Internal server error" });
  }
});

额外建议

  • 不要使用AWS根用户凭证,创建专用IAM用户并分配最小权限(比如仅允许对Users表执行GetItem操作),提升安全性
  • 文档客户端(@aws-sdk/lib-dynamodb)比低级客户端更易用,建议统一使用文档客户端的API,避免格式混用问题

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 20:23:16