错误处理

更新时间:
复制 MD 格式
一键部署
我的部署

本文介绍Node.js运行环境的错误处理相关内容。

错误类型

捕获异常

如果函数在执行过程中抛出异常,函数计算会捕获到错误,并生成一个包含错误信息、类型和堆栈信息的JSON格式的数据,示例如下所示。

ES模块

说明
  • 此示例仅支持运行在Node.js 18及以上版本的运行时环境。

  • 当前示例代码支持一键部署到函数计算FC。nodejs-fc-err-es

export const handler = async (event, context) => {
  throw new Error('oops');
};

CommonJS模块

exports.handler = function(event, context, callback) {
  throw new Error('oops');
};

收到的响应示例如下所示。

{
    "errorMessage": "oops",
    "errorType": "Error",
    "stackTrace": [
        "Error: oops",
        "    at handler (file:///code/index.mjs:2:9)",
        "    at module.exports (file:///var/fc/runtime/nodejs20/bootstrap.mjs:5655:14)",
        "    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)"
    ]
}

异常退出

如果函数在运行过程中主动退出,系统会返回一个通用的错误信息。

ES模块

说明

此示例仅支持运行在Node.js 18及以上版本的运行时环境。

export const handler = async (event, context) => {
  process.exit(1);
};

CommonJS模块

exports.handler = function(event, context, callback) {
  process.exit(1);
};

收到的响应如下所示。

{
    "errorMessage": "Process exited unexpectedly before completing request (duration: 12ms, maxMemoryUsage: 0MB)"
}

错误排查

如果函数计算遇到错误,则会返回HTTP状态代码、响应消息和表明错误原因的异常类型。调用函数的客户端或服务可以通过编程方式处理错误或将其传递到终端用户。

以下列表描述了可从函数中接收的状态码范围。

  • 2xx

    2xx系列状态代码表示函数计算已接收到请求。如果响应中包含X-Fc-Error-Type消息头,则表明函数计算捕获到了函数错误(比如代码中抛出的异常)。

  • 4xx

    4xx系列错误(不包括429)通常说明发起调用的客户端存在错误。

    429表示请求被限流。

  • 5xx

    5xx系列错误表示函数计算内部错误,或者函数的配置或资源存在问题。

有关调用错误的更多信息,请参见重试机制。

常见问题

require is not defined in ES module scope

现象

Node.js 函数的入口文件以 ES 模块方式加载(扩展名为.mjs,或package.json中设置了"type": "module"),且代码中使用require()加载模块时,调用返回 HTTP 状态码 200,响应头包含X-Fc-Error-Type: InvocationError,响应体报错如下所示。

{
    "errorMessage": "require is not defined in ES module scope, you can use import instead",
    "errorType": "ReferenceError",
    "stackTrace": [
        "ReferenceError: require is not defined in ES module scope, you can use import instead",
        "    at file:///code/index.mjs:1:15",
        "    at ModuleJob.run (node:internal/modules/esm/module_job:218:25)"
    ]
}

报错内容随入口文件类型和require()所在位置变化:

  • 入口文件为.js且package.json中设置了"type": "module"时,errorMessage追加一行说明:This file is being treated as an ES module because it has a '.js' file extension and '/code/package.json' contains "type": "module". To treat it as a CommonJS script, rename it to use the '.cjs' file extension.。

  • require()写在 handler 函数内部而非模块顶层时,errorMessage为require is not defined。

原因

require()是 CommonJS 模块系统的加载函数,在 ES 模块作用域中不可用。文件被识别为 ES 模块后,Node.js 不会注入require、module、exports等 CommonJS 变量。

解决方案

按代码结构选择以下任一方式:

  • 将require()改写为 ES 模块的import语句,需动态加载模块时使用import()表达式。

  • 保留require()写法时,将入口文件扩展名改为.cjs,函数 Handler 配置无需调整。

ES 模块改写示例(入口文件index.mjs)如下所示。

// 引入Node.js内置模块和本地ES模块文件
import { createHash } from 'node:crypto';
import { helper } from './utils.mjs';

export const handler = async (event, context) => {
  return createHash('sha256').update(helper()).digest('hex');
};

动态加载模块示例如下所示。

const crypto = await import('node:crypto');

CommonJS 写法示例(入口文件index.cjs)如下所示。

const crypto = require('crypto');

exports.handler = async (event, context) => {
  return crypto.createHash('sha256').digest('hex');
};
注意:加载第三方依赖包(如 lodash)时,需先在本地执行 npm install 安装依赖,再将 node_modules 目录与代码一起打包部署;ES 模块中可通过默认导入引用 CommonJS 依赖包,例如 import _ from 'lodash';。

ES 模块仅支持 Node.js 18 及以上运行时。使用 Node.js 16 及以下运行时时,.mjs入口文件不会被加载,调用返回"errorMessage": "Module '/code/index.js' is missing."和"errorType": "FunctionUnhandledError: ImportModuleError"。