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

使用AWS SDK v3操作DynamoDB遇UnrecognizedClientException错误排查

问题:AWS SDK v3连接DynamoDB出现UnrecognizedClientException错误

测试AWS SDK v3编写的DynamoDB操作代码时,抛出错误:

UnrecognizedClientException: The security token included in the request is invalid.

错误栈如下:

Unit test for DynamoDb ' verifies successful response

    UnrecognizedClientException: The security token included in the request is invalid.

      25 | const command = new GetItemCommand(params);
      26 | console.log(command)
    > 27 | const result = await this.client.send(command);
         | ^ ^
      28 | return { body: JSON.stringify(unmarshall(result.Item || {})) }; }
      29 | } catch (err: unknown) {
      30 | throw err;

相关代码:

import { BatchGetItemCommand, BatchWriteItemCommand, BatchWriteItemCommandOutput, DynamoDBClient, GetItemCommand, PutItemCommand, UpdateItemCommand } from '@aws-sdk/client-dynamodb';
import { marshall, unmarshall } from '@aws-sdk/util-dynamodb';

export class DynamoDb {
    private readonly tableName: string;
    private readonly client: DynamoDBClient;

    constructor(tableName = '') {
        this.client = new DynamoDBClient({
            region: 'ap-northeast-1',
            credentials: {
                accessKeyId: 'xxxx',
                secretAccessKey: 'xxxxx',
            },
        });
        this.tableName = tableName ? tableName : '';
    }

    public async get(keyName: string, key: string | number) {
        try {
            const params = {
                TableName: this.tableName,
                Key: marshall({ [keyName]: key }),
            };
            const command = new GetItemCommand(params);
            console.log(command)
            const result = await this.client.send(command);
            return { body: JSON.stringify(unmarshall(result.Item || {})) };
        } catch (err: unknown) {
            throw err;
        }
    }

    public async put(item: object) {
        try {
            const params = {
                TableName: this.tableName,
                Item: marshall(item),
            };
            const command = new PutItemCommand(params);
            return await this.client.send(command);
        } catch (err: unknown) {
            throw err;
        }
    }

    public async update(keyName: string, key: string | number, updateExpression: string, expressionAttributeValues: { [key: string]: any }) {
        try {
            const params = {
                TableName: this.tableName,
                Key: marshall({ [keyName]: key }),
                UpdateExpression: updateExpression,
                ExpressionAttributeValues: marshall(expressionAttributeValues),
                ReturnValues: 'ALL_NEW', // Return the updated attributes of the item
            };
            const command = new UpdateItemCommand(params);
            const result = await this.client.send(command);
            return { body: JSON.stringify(unmarshall(result.Attributes || {})) };
        } catch (err: unknown) {
            throw err;
        }
    }

    public async batchGet(keys: { [keyName: string]: string | number }[]) {
        try {
            const params = {
                RequestItems: {
                    [this.tableName]: {
                        Keys: keys.map((key) => marshall(key)),
                    },
                },
            };
            const command = new BatchGetItemCommand(params);
            const result = await this.client.send(command);
            const responses = result.Responses?.[this.tableName] || [];
            const items = responses.map((response) => unmarshall(response) as object);
            return { body: JSON.stringify(items) };
        } catch (err: unknown) {
            throw err;
        }
    }

    public async batchPut(items: object[]) {
        try {
            const putRequests = items.map((item) => ({
                PutRequest: {
                    Item: marshall(item),
                },
            }));

            const params = {
                RequestItems: {
                    [this.tableName]: putRequests,
                },
            };
            const command = new BatchWriteItemCommand(params);
            const result: BatchWriteItemCommandOutput = await this.client.send(command);
            return { body: JSON.stringify(result) };
        } catch (err: unknown) {
            throw err;
        }
    }
}

已知代码中已显式配置accessKeyId和secretAccessKey,且该密钥在其他代码中可正常连接DynamoDB,询问问题原因。


可能的原因及解决方法
  • 测试环境凭证优先级覆盖:AWS SDK v3会优先从环境变量、本地~/.aws/credentials文件或IAM角色加载凭证,可能你的测试环境里存在无效凭证(比如环境变量AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY被错误设置),覆盖了代码里显式配置的密钥。可以在测试代码里禁用凭证链查找,或者清理测试环境的相关环境变量。
  • 凭证配置验证:在DynamoDb构造函数里打印this.client.config.credentials,确认实际传入的密钥和你预期的有效密钥一致,避免代码里的占位符没替换、或者字符串拼写错误。
  • 临时凭证缺失参数:如果使用的是STS生成的临时凭证,必须在credentials里补充sessionToken字段,只传accessKeyId和secretAccessKey会导致验证失败。
  • 区域或权限不匹配:确认你的DynamoDB表确实在ap-northeast-1区域,且该密钥对应的IAM用户拥有该区域DynamoDB的操作权限(比如dynamodb:GetItem)。
  • 测试框架干扰:部分测试框架(如Jest)可能会模拟AWS客户端或重置环境变量,检查测试代码中是否存在对DynamoDBClient的Mock逻辑,或者是否有环境变量的重置操作。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 07:48:18