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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 11:59:56