Node.js 14转18的Lambda函数迁移语法错误排查求助
问题
将Lambda函数从Node.js 14迁移到Node.js 18后,代码出现JSON.parse语法错误:Unexpected token u in JSON at position 0,报错栈指向handler中解析event.body的位置。已确认使用Node.js 18版本Layer,环境不再支持CJS语法,此前从零创建Node.js 18函数时该语法可正常运行。
相关代码
import moment from 'moment'; import { QueryCommand, DynamoDBDocumentClient } from "@aws-sdk/lib-dynamodb"; import { DynamoDBClient } from "@aws-sdk/client-dynamodb"; const dynamoDBClient = new DynamoDBClient({ signatureVersion: "v4"}); const docClient = DynamoDBDocumentClient.from(dynamoDBClient); var startOfWeek = ""; var endOfWeek = ""; if (moment().isoWeekday() == 6) { startOfWeek = moment() .subtract(1, "weeks") .day("Saturday") .startOf("day") .toDate() .toISOString(); endOfWeek = moment() .subtract(0, "weeks") .day("Friday") .endOf("day") .toDate() .toISOString() } else { startOfWeek = moment() .subtract(2, "weeks") .day("Saturday") .startOf("day") .toDate() .toISOString(); endOfWeek = moment() .subtract(1, "weeks") .day("Friday") .endOf("day") .toDate() .toISOString(); } export const handler = async (event) => { let response = {}; let { agents } = JSON.parse(event.body); for(let index in agents){ let agentLogin = agents[index] let sampleData = await getSamples(agentLogin); response[agentLogin] = sampleData; } return { statusCode: 200, body: JSON.stringify(response), }; }; async function getSamples(userLogin){ //code to get sample and it will return an array }
错误信息
{ "errorType": "SyntaxError", "errorMessage": "Unexpected token u in JSON at position 0", "trace": [ "SyntaxError: Unexpected token u in JSON at position 0", " at JSON.parse (<anonymous>)", " at Runtime.handler (file:///var/task/index.mjs:39:27)", " at Runtime.handleOnceNonStreaming (file:///var/runtime/index.mjs:1147:29)" ] }
问题原因
Unexpected token u是JSON解析的典型错误,本质是event.body为undefined——JSON.parse(undefined)会尝试解析字符串"undefined",第一个字符就是u,触发报错。
迁移到Node.js 18后出现该问题的核心原因:
- Lambda Node.js 18运行时对事件格式的处理逻辑和Node.js 14存在差异,比如API Gateway触发时,空请求体或GET请求不会自动填充
event.body,直接返回undefined; - 旧代码在Node.js 14中可能依赖了某些隐式的
event.body默认值,迁移后这些默认值不再存在; - 代码未对
event.body做合法性校验,直接执行JSON.parse导致报错。
解决方法
- 添加参数校验与异常捕获
在解析前先检查event.body是否存在,同时捕获JSON解析异常,避免程序崩溃:
export const handler = async (event) => { let response = {}; // 校验请求体是否存在 if (!event.body) { return { statusCode: 400, body: JSON.stringify({ error: "请求体不能为空" }) }; } try { let { agents } = JSON.parse(event.body); // 校验agents是否为有效数组 if (!Array.isArray(agents)) { return { statusCode: 400, body: JSON.stringify({ error: "agents必须为数组格式" }) }; } for(let index in agents){ let agentLogin = agents[index] let sampleData = await getSamples(agentLogin); response[agentLogin] = sampleData; } return { statusCode: 200, body: JSON.stringify(response), }; } catch (err) { // 捕获解析错误或其他异常 return { statusCode: 400, body: JSON.stringify({ error: "请求体格式错误:" + err.message }) }; } };
- 检查触发方式
- 若通过API Gateway触发,确保使用POST/PUT等带请求体的方法,且请求头
Content-Type设置为application/json; - 若使用测试事件触发,确保测试事件的
body字段为合法JSON字符串(例如"{\"agents\": [\"user1\", \"user2\"]}")。
- 确认ESM语法规范
确保代码完全使用ESM语法(import/export):
- 文件后缀为
.mjs,或在package.json中添加"type": "module"配置,避免混合CJS语法导致隐性问题。
内容的提问来源于stack exchange,提问作者helloi
相关产品推荐
相关产品推荐

