diff --git a/infra/smalruby-classroom/lambda/handler.ts b/infra/smalruby-classroom/lambda/handler.ts index 46daa8204d..8030532f9a 100644 --- a/infra/smalruby-classroom/lambda/handler.ts +++ b/infra/smalruby-classroom/lambda/handler.ts @@ -3752,14 +3752,17 @@ async function handleListSharedAssignments( } } + // DynamoDB rejects an EMPTY ExpressionAttributeNames map, so the key must + // be omitted when there is nothing to alias (mine=1 with no filters). + const expressionNames = { + ...(mine ? {} : { '#status': 'status' }), + ...names, + }; const result = await docClient.send(new QueryCommand({ TableName: SHARED_ASSIGNMENTS_TABLE, IndexName: mine ? 'authorSub-createdAt-index' : 'status-createdAt-index', KeyConditionExpression: mine ? 'authorSub = :pk' : '#status = :pk', - ExpressionAttributeNames: { - ...(mine ? {} : { '#status': 'status' }), - ...names, - }, + ...(Object.keys(expressionNames).length > 0 ? { ExpressionAttributeNames: expressionNames } : {}), ExpressionAttributeValues: { ':pk': mine ? identity.sub : 'published', ...values, diff --git a/infra/smalruby-classroom/lambda/tests/handler-shared-assignments.test.ts b/infra/smalruby-classroom/lambda/tests/handler-shared-assignments.test.ts index 9127b2ead1..e59833fa55 100644 --- a/infra/smalruby-classroom/lambda/tests/handler-shared-assignments.test.ts +++ b/infra/smalruby-classroom/lambda/tests/handler-shared-assignments.test.ts @@ -325,6 +325,10 @@ describe('みんなの課題 (issue #1068)', () => { })); expect(captured?.IndexName).toBe('authorSub-createdAt-index'); expect((captured?.ExpressionAttributeValues as Record)[':pk']).toBe('dev-test-teacher'); + // DynamoDB rejects an EMPTY ExpressionAttributeNames map — with no + // filters and no #status alias, the key must be omitted entirely + // (prod 500 on 自分の投稿, 2026-07-18). + expect(captured?.ExpressionAttributeNames).toBeUndefined(); expect(JSON.parse(res.body as string).items[0].status).toBe('unlisted'); }); });