AWS Amplify Gen2 REST API写入DynamoDB报错ResourceNotFoundException
问题:Lambda写入DynamoDB时触发ResourceNotFoundException
使用AWS Amplify Hosting(Gen 2)搭建了Lambda支撑的REST API,Lambda发送邮件功能正常,但写入DynamoDB时出现以下错误:
ResourceNotFoundException: Requested resource not found
已确认表名正确,尝试过用具体表ARN和通配符放宽权限,问题仍存在。以下是API Stack和Lambda函数代码,寻求解决思路。
API Stack 代码(TypeScript)
// create a new API stack const apiStack = backend.createStack("api-stack"); // create a new REST API const myRestApi = new RestApi(apiStack, "RestApi", { restApiName: "myRestApi", deploy: true, deployOptions: { stageName: "dev", }, defaultCorsPreflightOptions: { allowOrigins: Cors.ALL_ORIGINS, // Restrict this to domains you trust allowMethods: Cors.ALL_METHODS, // Specify only the methods you need to allow allowHeaders: Cors.DEFAULT_HEADERS, // Specify only the headers you need to allow }, }); backend.ApiContactFormFunction.resources.lambda.addToRolePolicy( new PolicyStatement({ actions: ['ses:SendEmail', 'ses:SendRawEmail'], resources: ['*'] }), ) backend.ApiContactFormFunction.resources.lambda.addToRolePolicy( new PolicyStatement({ effect: Effect.ALLOW, actions: [ 'dynamodb:PutItem', ], resources: [ "*" ] }) ) // create a new Lambda integration const lambdaIntegration = new LambdaIntegration( backend.ApiContactFormFunction.resources.lambda ); // create a new resource path with IAM authorization const itemsPath = myRestApi.root.addResource("contact-form", { defaultMethodOptions: { authorizationType: AuthorizationType.NONE, }, }); // add methods you would like to create to the resource path itemsPath.addMethod("GET", lambdaIntegration); itemsPath.addMethod("POST", lambdaIntegration); itemsPath.addMethod("DELETE", lambdaIntegration); itemsPath.addMethod("PUT", lambdaIntegration); // add a proxy resource path to the API itemsPath.addProxy({ anyMethod: true, defaultIntegration: lambdaIntegration, }); // create a new IAM policy to allow Invoke access to the API const apiRestPolicy = new Policy(apiStack, "RestApiPolicy", { statements: [ new PolicyStatement({ actions: ["execute-api:Invoke"], resources: [ `${myRestApi.arnForExecuteApi("*", "/contact-form", "dev")}`, ], }), ], }); // attach the policy to the authenticated and unauthenticated IAM roles backend.auth.resources.authenticatedUserIamRole.attachInlinePolicy( apiRestPolicy ); backend.auth.resources.unauthenticatedUserIamRole.attachInlinePolicy( apiRestPolicy ); // add outputs to the configuration file backend.addOutput({ custom: { API: { [myRestApi.restApiName]: { endpoint: myRestApi.url, region: Stack.of(myRestApi).region, apiName: myRestApi.restApiName, }, }, }, });
Lambda 函数代码(TypeScript)
import type { APIGatewayProxyHandler, APIGatewayProxyHandlerV2 } from "aws-lambda"; import { DynamoDBClient, PutItemCommand } from "@aws-sdk/client-dynamodb"; import { SESClient, SendEmailCommand } from '@aws-sdk/client-ses'; const ddbClient = new DynamoDBClient({ region: 'eu-west-1' }); const sesClient = new SESClient({ region: 'af-south-1' }); export const handler: APIGatewayProxyHandler = async (event) => { console.log("event", event); const body = JSON.parse(event.body || '{}'); const { fullName, email, phoneNumber, message } = body; const recipient = 'test@gmail.com'; const subject = `Contact Form - ${fullName}`; const htmlTemplate = `Email Body`; const command = new SendEmailCommand({ Source: 'test@gmail.com', Destination: { ToAddresses: [recipient] }, Message: { Body: { Html: { Data: htmlTemplate } }, Subject: { Data: subject } } }); const response = { statusCode: 200, headers: { "Access-Control-Allow-Origin": "*", // Restrict this to domains you trust "Access-Control-Allow-Headers": "*", // Specify only the headers you need to allow }, body: '', }; try { const result = await sesClient.send(command); console.log(`Email sent to ${recipient}: ${result.MessageId}`); const tbCommand = new PutItemCommand({ TableName: 'Table', Item: { email: { S: 'Test email' }, message: { S: 'Test message' }, phone: { S: 'Test phone' }, fullName: { S: 'Fullname' } }, }); await ddbClient.send(tbCommand); response.body = JSON.stringify(`Email have been send to ${fullName} - ${email}}!`) } catch (error) { response.statusCode = 500; response.body = JSON.stringify(`There was an error sending the email: ${error}`) } return response; };
排查与解决思路
- 区域不匹配:Lambda代码中DynamoDB客户端指定区域为
eu-west-1,需确认DynamoDB表是否确实在该区域创建。若表在其他区域,修改客户端的region参数。 - 表名大小写/拼写问题:DynamoDB表名区分大小写,确保Lambda中
TableName: 'Table'与控制台显示的表名完全一致。 - IAM权限生效延迟:添加权限后,IAM策略可能需要数分钟才能生效,等待后重试。
- 表状态验证:登录AWS控制台确认DynamoDB表处于活跃状态,未被删除或仍在创建中。
- VPC配置冲突:若Lambda配置了VPC,需确保VPC有访问DynamoDB的权限(通过VPC端点或允许出站访问);若无需VPC,可移除Lambda的VPC配置。
内容的提问来源于stack exchange,提问作者dev.learn
相关产品推荐
相关产品推荐

