本文介紹Node.js運行環境的錯誤處理相關內容。
錯誤類型
捕獲異常
如果函數在執行過程中拋出異常,Function Compute會捕獲到錯誤,並產生一個包含錯誤資訊、類型和堆棧資訊的JSON格式的資料,樣本如下所示。
ES模組
-
此樣本僅支援運行在Node.js 18及以上版本的運行時環境。
-
當前範例程式碼支援一鍵部署到Function ComputeFC。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)"
}
錯誤排查
如果Function Compute遇到錯誤,則會返回HTTP狀態碼、響應訊息和表明錯誤原因的異常類型。調用函數的用戶端或服務可以通過編程方式處理錯誤或將其傳遞到終端使用者。
以下列表描述了可從函數中接收的狀態代碼範圍。
-
2xx
2xx系列狀態碼表示Function Compute已接收到請求。如果響應中包含
X-Fc-Error-Type訊息頭,則表明Function Compute捕獲到了函數錯誤(比如代碼中拋出的異常)。 -
4xx
4xx系列錯誤(不包括429)通常說明發起調用的用戶端存在錯誤。
429表示請求被限流。
-
5xx
5xx系列錯誤表示Function Compute內部錯誤,或者函數的配置或資源存在問題。
有關調用錯誤的更多資訊,請參見重試機制。
常見問題
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"。