AWS Amplify Gen2自定义Resolver中ctx.stash为空致表名错误
问题:AWS Amplify Gen 2自定义批量突变表名错误,ctx.stash为空
错误信息
DynamoDB:DynamoDbException", message: "User: arn:aws:sts::{AWS_ACCOUNT_ID}:assumed-role/MyGroupRole-XXXXX-NONE/APPSYNC_ASSUME_ROLE is not authorized to perform: dynamodb:BatchWriteItem on resource: arn:aws:dynamodb:us-west-2:{AWS_ACCOUNT_ID}:table/Group-- because no identity-based policy allows the dynamodb:BatchWriteItem action (Service: DynamoDb, Status Code: 400, Request ID: {REQUEST_ID})
问题核心:生成的表名为Group--,而非预期的完整表名。根据官方文档,应从ctx.stash获取awsAppsyncApiId和amplifyApiEnvironmentName拼接表名,但打印日志发现ctx.stash是空对象。
相关代码
amplify/data/resource.ts 突变定义
BatchUpdateGroupRanks: a.mutation().arguments({ resumeID: a.string(), ids: a.string().array().required(), ranks: a.integer().array().required(), }) .returns(a.ref('Group').array()) .authorization(allow => [allow.authenticated()]) .handler( a.handler.custom({ dataSource: a.ref('Group'), entry: './BatchUpdateGroupRanksHandler.js', }) ),
BatchUpdateGroupRanksHandler.js
export function request(ctx) { const tableName = `Group-${ctx.stash.awsAppsyncApiId}-${ctx.stash.amplifyApiEnvironmentName}`; const now = util.time.nowISO8601(); const updates = ctx.args.ids.map((id, index) => ({ id, rank: ctx.args.ranks[index], })); return { operation: 'BatchPutItem', tables: { [tableName]: updates.map((update) => util.dynamodb.toMapValues({ id: update.id, rank: update.rank, resumeID: ctx.args.resumeID, updatedAt: now, __typename: 'Group' }) ), }, }; } export function response(ctx) { if (ctx.error) { util.error(ctx.error.message, ctx.error.type); } return ctx.result.data[`Group-${ctx.stash.awsAppsyncApiId}-${ctx.stash.amplifyApiEnvironmentName}`]; }
已尝试操作
- 打印
ctx确认stash为空 - 验证
BatchWriteItem权限已配置 - 对比官方文档《Batch DynamoDB Operations》
- 硬编码表名可正常运行,但非最优方案
疑问
- 为什么
ctx.stash是空的? - 如何填充
ctx.stash? - 是否有其他方式动态获取
awsAppsyncApiId和amplifyApiEnvironmentName?
环境信息
- AWS Amplify Gen 2
- Angular 19
解决方案
1. 为什么ctx.stash是空的?
Amplify Gen 2的自定义resolver不会自动向ctx.stash注入awsAppsyncApiId和amplifyApiEnvironmentName,这和Gen 1的自动注入逻辑不同,需要手动配置注入。
2. 如何填充ctx.stash?
在amplify/data/resource.ts的自定义handler配置中,通过stash参数手动注入所需环境变量:
handler( a.handler.custom({ dataSource: a.ref('Group'), entry: './BatchUpdateGroupRanksHandler.js', // 手动注入stash变量 stash: { awsAppsyncApiId: a.env('AWS_APPSYNC_API_ID'), amplifyApiEnvironmentName: a.env('AMPLIFY_ENV_NAME') } }) ),
AMPLIFY_ENV_NAME由Amplify自动注入部署环境,无需额外配置AWS_APPSYNC_API_ID可通过amplify status命令、amplify_outputs.json文件或AppSync控制台获取
3. 其他动态获取表名的方式
方式一:直接从数据源获取表名
利用已关联的数据源,直接通过ctx.datasource.name获取Amplify自动生成的完整表名,无需拼接:
// 在request函数中修改 const tableName = ctx.datasource.name;
方式二:通过util.env读取环境变量
确保环境变量已配置在AppSync数据源的执行环境中,然后在handler中读取:
const apiId = util.env.get('AWS_APPSYNC_API_ID'); const envName = util.env.get('AMPLIFY_ENV_NAME'); const tableName = `Group-${apiId}-${envName}`;
额外注意事项
- 权限配置:可将IAM角色的
dynamodb:BatchWriteItem资源ARN设置为arn:aws:dynamodb:us-west-2:{AWS_ACCOUNT_ID}:table/Group-*,避免硬编码表名后缀 - 部署验证:修改配置后重新执行
amplify push部署资源,测试批量突变功能是否正常
内容的提问来源于stack exchange,提问作者SecretLumberjack
相关产品推荐
相关产品推荐

