Genesys Webhook payload in Lambda is undefined on retry

I’m seeing some weird behavior with a Node.js Lambda function that’s supposed to process Genesys Cloud routing events. The goal is to log queue member status changes. It works fine the first time, but when I force a retry by returning a 500, the event.body is suddenly undefined or an empty string.

Here is the handler code I’ve got so far:

exports.handler = async (event) => {
 console.log('Received event:', JSON.stringify(event));
 
 let body;
 try {
 // This fails on retries
 body = JSON.parse(event.body);
 } catch (e) {
 console.error('Parse error:', e);
 return {
 statusCode: 500,
 body: 'Bad payload'
 };
 }

 // Process body...
 return {
 statusCode: 200,
 body: JSON.stringify({ message: 'ok' })
 };
};

The first request comes in with a nice JSON string in event.body. But when Genesys retries, the event object looks different. The logs show event.body is null. I’m checking the Genesys admin panel and the webhook is definitely set to retry on 5xx errors.

Is there something I’m missing about how the API Gateway or Lambda handles the payload on retries? I’ve tried adding isBase64Encoded checks but that didn’t help. The raw logs from the first call look normal:

{"httpMethod":"POST","body":"{\"event\":\"routing.queue.member.status\"...}","headers":{"Content-Type":"application/json"}}

But the retry log just shows:

{"httpMethod":"POST","body":null,"headers":{}}

It’s driving me mad. I don’t get why the body would vanish. I’ve checked the IAM roles and they seem fine for writing to CloudWatch. Any ideas on what’s stripping the body?