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

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》
  • 硬编码表名可正常运行,但非最优方案

疑问

  1. 为什么ctx.stash是空的?
  2. 如何填充ctx.stash?
  3. 是否有其他方式动态获取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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 08:42:33