错误
目录
-
- Node.js 中的错误处理
- Fastify 中的错误
- Fastify 生命周期钩子和自定义错误处理程序中的错误
- Fastify 错误代码
- FST_ERR_NOT_FOUND
- FST_ERR_OPTIONS_NOT_OBJ
- FST_ERR_QSP_NOT_FN
- FST_ERR_SCHEMA_CONTROLLER_BUCKET_OPT_NOT_FN
- FST_ERR_SCHEMA_ERROR_FORMATTER_NOT_FN
- FST_ERR_AJV_CUSTOM_OPTIONS_OPT_NOT_OBJ
- FST_ERR_AJV_CUSTOM_OPTIONS_OPT_NOT_ARR
- FST_ERR_CTP_ALREADY_PRESENT
- FST_ERR_CTP_INVALID_TYPE
- FST_ERR_CTP_EMPTY_TYPE
- FST_ERR_CTP_INVALID_HANDLER
- FST_ERR_CTP_INVALID_PARSE_TYPE
- FST_ERR_CTP_BODY_TOO_LARGE
- FST_ERR_CTP_INVALID_MEDIA_TYPE
- FST_ERR_CTP_INVALID_CONTENT_LENGTH
- FST_ERR_CTP_EMPTY_JSON_BODY
- FST_ERR_CTP_INSTANCE_ALREADY_STARTED
- FST_ERR_INSTANCE_ALREADY_LISTENING
- FST_ERR_DEC_ALREADY_PRESENT
- FST_ERR_DEC_DEPENDENCY_INVALID_TYPE
-
- FST_ERR_DEC_DEPENDENCY_INVALID_TYPE
- FST_ERR_DEC_MISSING_DEPENDENCY
- FST_ERR_DEC_AFTER_START
- FST_ERR_DEC_REFERENCE_TYPE
- FST_ERR_DEC_UNDECLARED
- FST_ERR_HOOK_INVALID_TYPE
- FST_ERR_HOOK_INVALID_HANDLER
- FST_ERR_HOOK_INVALID_ASYNC_HANDLER
- FST_ERR_HOOK_NOT_SUPPORTED
- FST_ERR_MISSING_MIDDLEWARE
- FST_ERR_HOOK_TIMEOUT
- FST_ERR_LOG_INVALID_DESTINATION
- FST_ERR_LOG_INVALID_LOGGER
- FST_ERR_LOG_INVALID_LOGGER_INSTANCE
- FST_ERR_LOG_INVALID_LOGGER_CONFIG
- FST_ERR_LOG_LOGGER_AND_LOGGER_INSTANCE_PROVIDED
- FST_ERR_REP_INVALID_PAYLOAD_TYPE
- FST_ERR_REP_RESPONSE_BODY_CONSUMED
- FST_ERR_REP_READABLE_STREAM_LOCKED
- FST_ERR_REP_ALREADY_SENT
- FST_ERR_REP_SENT_VALUE
- FST_ERR_SEND_INSIDE_ONERR
- FST_ERR_SEND_UNDEFINED_ERR
- FST_ERR_BAD_STATUS_CODE
- FST_ERR_BAD_TRAILER_NAME
- FST_ERR_BAD_TRAILER_VALUE
- FST_ERR_FAILED_ERROR_SERIALIZATION
-
- FST_ERR_FAILED_ERROR_SERIALIZATION
- FST_ERR_MISSING_SERIALIZATION_FN
- FST_ERR_MISSING_CONTENTTYPE_SERIALIZATION_FN
- FST_ERR_REQ_INVALID_VALIDATION_INVOCATION
- FST_ERR_SCH_MISSING_ID
- FST_ERR_SCH_ALREADY_PRESENT
- FST_ERR_SCH_CONTENT_MISSING_SCHEMA
- FST_ERR_SCH_DUPLICATE
- FST_ERR_SCH_VALIDATION_BUILD
- FST_ERR_SCH_SERIALIZATION_BUILD
- FST_ERR_SCH_RESPONSE_SCHEMA_NOT_NESTED_2XX
- FST_ERR_INIT_OPTS_INVALID
- FST_ERR_FORCE_CLOSE_CONNECTIONS_IDLE_NOT_AVAILABLE
- FST_ERR_DUPLICATED_ROUTE
- FST_ERR_BAD_URL
- FST_ERR_ASYNC_CONSTRAINT
- FST_ERR_INVALID_URL
- FST_ERR_ROUTE_OPTIONS_NOT_OBJ
- FST_ERR_ROUTE_DUPLICATED_HANDLER
- FST_ERR_ROUTE_HANDLER_NOT_FN
- FST_ERR_ROUTE_MISSING_HANDLER
- FST_ERR_ROUTE_METHOD_INVALID
- FST_ERR_ROUTE_METHOD_NOT_SUPPORTED
- FST_ERR_ROUTE_BODY_VALIDATION_SCHEMA_NOT_SUPPORTED
- FST_ERR_ROUTE_BODY_LIMIT_OPTION_NOT_INT
- FST_ERR_ROUTE_REWRITE_NOT_STR
Node.js中的错误处理
未捕获的错误
在Node.js中,未捕获的错误可能导致内存泄漏、文件描述符泄漏以及其他重大生产问题。 Domains 是一种尝试解决此问题但失败的方法。
鉴于无法合理处理所有未捕获的错误,最好的方法是 崩溃 。
在Promise中捕获错误
使用Promise时,请同步附加一个.catch()
处理器。
Fastify中的错误
Fastify采取全有或全无的方法,并力求精简和优化。开发人员负责确保正确处理所有错误。
输入数据中的错误
大多数错误源于意外的输入数据,因此建议对输入数据进行JSON模式验证。
在Fastify中捕获未捕获的错误
Fastify尝试在不影响性能的情况下尽可能多地捕获未捕获的错误。这包括:
- 同步路由,例如
app.get('/', () => { throw new Error('kaboom') })
- 异步路由,例如
app.get('/', async () => { throw new Error('kaboom') })
在这两种情况下,错误将被安全捕获并传递给Fastify的默认错误处理器,导致返回一个通用的500 Internal Server Error
响应。
要自定义此行为,请使用
setErrorHandler
。
Fastify 生命周期钩子中的错误及自定义错误处理程序
从 Hooks 文档:
如果在执行您的钩子时遇到错误,请将其传递给
done()
,Fastify 将自动关闭请求并向用户发送适当的错误代码。
当通过
setErrorHandler
定义自定义错误处理程序时,它将接收传递给 done()
回调或通过其他支持的自动错误处理机制传递的错误。如果多次使用 setErrorHandler
,则错误会被路由到错误封装上下文中的最优先级处理器。错误处理程序是完全封装的,因此插件内的 setErrorHandler
调用将限制错误处理程序仅在该插件的上下文中有效。
根错误处理程序是 Fastify 的通用错误处理程序。此错误处理程序会使用 Error
对象中的头信息和状态码(如果存在)。如果提供了自定义错误处理程序,则不会自动设置头信息和状态码。
使用自定义错误处理程序时应考虑以下事项:
-
reply.send(data)
行为与 常规路由处理器 相同- 对象会被序列化,触发
preSerialization
生命周期钩子(如果已定义) - 字符串、缓冲区和流会以适当的头信息发送给客户端(不进行序列化)
- 对象会被序列化,触发
-
在自定义错误处理程序中抛出新的错误将调用父级的
errorHandler
。- 对于首次抛出的错误,
onError
钩子会被触发一次 - 生命周期钩子阶段不会两次触发同一个错误。Fastify 内部监控错误调用来避免在回复阶段(路由处理器之后)抛出错误时出现无限循环
- 对于首次抛出的错误,
当使用Fastify的自定义错误处理功能时,通过setErrorHandler
,请注意自定义和默认错误处理器之间如何传播错误。
如果插件中的错误处理器重新抛出一个不是Error 实例的错误,则该错误不会传递到父上下文的错误处理器。相反,它将被捕获并由默认错误处理器处理。这可以在下面示例中的/bad
路由中看到。
为了确保一致的错误处理,请抛出Error
类型的实例。例如,在/bad
路由中,用throw new Error('foo')
替换throw 'foo'
以确保错误能够按照预期通过自定义错误处理链传播。这种做法有助于避免在使用Fastify时进行自定义错误处理时可能出现的问题。
例如:
const Fastify = require('fastify')
// 初始化框架
const fastify = Fastify({
logger: true
})
// 注册父级错误处理器
fastify.setErrorHandler((error, request, reply) => {
reply.status(500).send({ ok: false })
})
fastify.register((app, options, next) => {
// 注册子级错误处理器
fastify.setErrorHandler((error, request, reply) => {
throw error
})
fastify.get('/bad', async () => {
// 抛出一个非Error类型的错误,'foo'
throw 'foo'
})
fastify.get('/good', async () => {
// 抛出一个Error实例,'bar'
throw new Error('bar')
})
next()
})
// 启动服务器
fastify.listen({ port: 3000 }, function (err, address) {
if (err) {
fastify.log.error(err)
process.exit(1)
}
// 服务器正在${address}监听
})
Fastify 错误代码
您可以访问 errorCodes
进行映射:
// ESM
import { errorCodes } from 'fastify'
// CommonJS
const errorCodes = require('fastify').errorCodes
例如:
const Fastify = require('fastify')
// 实例化框架
const fastify = Fastify({
logger: true
})
// 声明一个路由
fastify.get('/', function (request, reply) {
reply.code('bad status code').send({ hello: 'world' })
})
fastify.setErrorHandler(function (error, request, reply) {
if (error instanceof Fastify.errorCodes.FST_ERR_BAD_STATUS_CODE) {
// 记录错误
this.log.error(error)
// 发送错误响应
reply.status(500).send({ ok: false })
} else {
// Fastify 将使用父级错误处理程序来处理此错误
reply.send(error)
}
})
// 启动服务器!
fastify.listen({ port: 3000 }, function (err, address) {
if (err) {
fastify.log.error(err)
process.exit(1)
}
// 服务器现在正在 ${address} 监听
})
以下是Fastify 使用的所有错误代码的表格。
代码 | 描述 | 解决方法 | 讨论 |
---|---|---|---|
FST_ERR_NOT_FOUND | 404 Not Found | - | #1168 |
FST_ERR_OPTIONS_NOT_OBJ | Fastify选项指定错误。 | 快速启动选项应该是一个对象。 | #4554 |
FST_ERR_QSP_NOT_FN | QueryStringParser指定错误。 | QueryStringParser选项应为一个函数。 | #4554 |
FST_ERR_SCHEMA_CONTROLLER_BUCKET_OPT_NOT_FN | SchemaController.bucket指定错误。 | SchemaController.bucket选项应为一个函数。 | #4554 |
FST_ERR_SCHEMA_ERROR_FORMATTER_NOT_FN | SchemaErrorFormatter选项指定错误。 | SchemaErrorFormatter选项应为一个非异步函数。 | #4554 |
FST_ERR_AJV_CUSTOM_OPTIONS_OPT_NOT_OBJ | ajv.customOptions指定错误。 | ajv.customOptions选项应为一个对象。 | #4554 |
FST_ERR_AJV_CUSTOM_OPTIONS_OPT_NOT_ARR | ajv.plugins选项指定错误。 | ajv.plugins选项应为一个数组。 | #4554 |
FST_ERR_CTP_ALREADY_PRESENT | 此内容类型的解析器已注册。 | 使用不同的内容类型或删除已注册的解析器。 | #1168 |
FST_ERR_CTP_INVALID_TYPE | Content-Type 指定错误 | Content-Type 应该是一个字符串。 | #1168 |
FST_ERR_CTP_EMPTY_TYPE | Content-Type 是空字符串。 | Content-Type 不能是空字符串。 | #1168 |
FST_ERR_CTP_INVALID_HANDLER | 内容类型的处理程序无效。 | 使用不同的处理程序。 | #1168 |
FST_ERR_CTP_INVALID_PARSE_TYPE | 提供的解析类型不受支持。 | 接受的值为 string 或 buffer 。 | #1168 |
FST_ERR_CTP_BODY_TOO_LARGE | 请求体大于提供的限制。 | 在 Fastify 服务器实例设置中增加限制:bodyLimit | #1168 |
FST_ERR_CTP_INVALID_MEDIA_TYPE | 接收的媒体类型不受支持(即没有合适的 Content-Type 解析器)。 | 使用不同的内容类型。 | #1168 |
FST_ERR_CTP_INVALID_CONTENT_LENGTH | 请求体大小与 Content-Length 不匹配。 | 检查请求体大小和 Content-Length 标头。 | #1168 |
FST_ERR_CTP_EMPTY_JSON_BODY | 当内容类型设置为 application/json 时,请求体不能为空。 | 检查请求体。 | #1253 |
FST_ERR_CTP_INSTANCE_ALREADY_STARTED | Fastify 已经启动。 | - | #4554 |
FST_ERR_INSTANCE_ALREADY_LISTENING | Fastify 实例已经在监听。 | - | #4554 |
FST_ERR_DEC_ALREADY_PRESENT | 已注册的装饰器名称相同。 | 使用不同的装饰器名称。 | #1168 |
FST_ERR_DEC_DEPENDENCY_INVALID_TYPE | 装饰器的依赖项必须为 Array 类型。 | 使用数组来定义依赖项。 | #3090 |
FST_ERR_DEC_MISSING_DEPENDENCY | 由于缺少依赖项,无法注册该装饰器。 | 注册缺失的依赖项。 | #1168 |
FST_ERR_DEC_AFTER_START | 不能在启动之后添加装饰器。 | 在启动服务器之前添加装饰器。 | #2128 |
FST_ERR_DEC_REFERENCE_TYPE | 装饰器不能是引用类型。 | 使用 getter/setter 接口定义装饰器,或使用空装饰器和钩子。 | #5462 |
FST_ERR_DEC_UNDECLARED | 尝试访问尚未声明的装饰器。 | 在使用之前声明该装饰器。 | # |
FST_ERR_HOOK_INVALID_TYPE | 钩子名称必须为字符串。 | 使用字符串作为钩子名称。 | #1168 |
FST_ERR_HOOK_INVALID_HANDLER | 钩子回调必须是函数。 | 使用函数作为钩子回调。 | #1168 |
FST_ERR_HOOK_INVALID_ASYNC_HANDLER | 异步函数参数过多。异步钩子不应使用done 参数。 | 从异步钩子中移除done 参数。 | #4367 |
FST_ERR_HOOK_NOT_SUPPORTED | 钩子不受支持。 | 使用受支持的钩子。 | #4554 |
FST_ERR_MISSING_MIDDLEWARE | 必须注册一个处理中间件的插件,更多信息请访问Middleware 。 | 注册一个处理中间件的插件。 | #2014 |
FST_ERR_HOOK_TIMEOUT | 钩子回调超时。 | 增加钩子的超时时间。 | #3106 |
FST_ERR_LOG_INVALID_DESTINATION | 日志记录器不接受指定的目标。 | 使用'stream' 或'file' 作为目标。 | #1168 |
FST_ERR_LOG_INVALID_LOGGER | 日志记录器应具有以下方法:'info' , 'error' , 'debug' , 'fatal' , 'warn' , 'trace' , 'child' 。 | 使用包含所有必需方法的日志记录器。 | #4520 |
FST_ERR_LOG_INVALID_LOGGER_INSTANCE | loggerInstance 只接受一个日志实例,而不是配置对象。 | 要传递配置对象,请使用 'logger' 替代。 | #5020 |
FST_ERR_LOG_INVALID_LOGGER_CONFIG | 日志选项只接受一个配置对象,而不是日志实例。 | 要传递实例,请使用 'loggerInstance' 替代。 | #5020 |
FST_ERR_LOG_LOGGER_AND_LOGGER_INSTANCE_PROVIDED | 不能同时提供 'logger' 和 'loggerInstance' 。 | 请只提供一个选项。 | #5020 |
FST_ERR_REP_INVALID_PAYLOAD_TYPE | 回复有效负载可以是 string 或 Buffer 类型。 | 使用 string 或 Buffer 作为有效负载。 | #1168 |
FST_ERR_REP_RESPONSE_BODY_CONSUMED | 使用 Response 作为回复有效负载,但响应体已被消费。 | 确保不要消费 Response.body | #5286 |
FST_ERR_REP_READABLE_STREAM_LOCKED | 使用 ReadableStream 作为回复有效负载,但已被其他读者锁定。 | 确保在发送之前不要调用 Readable.getReader() 或使用 reader.releaseLock() 在发送前释放锁。 | #5920 |
FST_ERR_REP_ALREADY_SENT | 已经发送了一个响应。 | - | #1336 |
FST_ERR_REP_SENT_VALUE | reply.sent 的唯一可能值是 true 。 | - | #1336 |
FST_ERR_SEND_INSIDE_ONERR | 不能在 onError 钩子中使用 send 。 | - | #1348 |
FST_ERR_SEND_UNDEFINED_ERR | 发生了未定义的错误。 | - | #2074 |
FST_ERR_BAD_STATUS_CODE | 状态码无效。 | 使用有效状态码。 | #2082 |
FST_ERR_BAD_TRAILER_NAME | 传入 reply.trailer 的头信息名称无效。 | 使用有效的头信息名称。 | #3794 |
FST_ERR_BAD_TRAILER_VALUE | 传入 reply.trailer 的类型无效,期望为函数。 | 使用函数。 | #3794 |
FST_ERR_FAILED_ERROR_SERIALIZATION | 错误序列化失败。 | - | #4601 |
FST_ERR_MISSING_SERIALIZATION_FN | 缺少序列化函数。 | 添加序列化函数。 | #3970 |
FST_ERR_MISSING_CONTENTTYPE_SERIALIZATION_FN | 缺少 Content-Type 序列化函数。 | 添加序列化函数。 | #4264 |
FST_ERR_REQ_INVALID_VALIDATION_INVOCATION | 无效的验证调用。HTTP部分缺少验证函数,也没有提供模式。 | 添加一个验证函数。 | #3970 |
FST_ERR_SCH_MISSING_ID | 提供的模式没有 $id 属性。 | 添加一个 $id 属性。 | #1168 |
FST_ERR_SCH_ALREADY_PRESENT | 已经存在具有相同 $id 的模式。 | 使用不同的 $id 。 | #1168 |
FST_ERR_SCH_CONTENT_MISSING_SCHEMA | 对应的内容类型缺少模式。 | 添加一个模式。 | #4264 |
FST_ERR_SCH_DUPLICATE | 具有相同属性的模式已经存在! | 使用不同的属性。 | #1954 |
FST_ERR_SCH_VALIDATION_BUILD | 提供给路由验证的 JSON 模式无效。 | 修复 JSON 模式。 | #2023 |
FST_ERR_SCH_SERIALIZATION_BUILD | 提供给路由响应序列化的 JSON 模式无效。 | 修复 JSON 模式。 | #2023 |
FST_ERR_SCH_RESPONSE_SCHEMA_NOT_NESTED_2XX | 响应模式应该嵌套在有效的状态代码(2XX)下。 | 使用有效的状态代码。 | #4554 |
FST_ERR_INIT_OPTS_INVALID | 初始化选项无效。 | 使用有效的初始化选项。 | #1471 |
FORCE_CLOSE_CONNECTIONS_IDLE_NOT_AVAILABLE | 将 forceCloseConnections 设置为 idle 不可用,因为您的 HTTP 服务器不支持 closeIdleConnections 方法。 | 使用不同的值设置 forceCloseConnections 。 | #3925 |
DUPLICATE_ROUTE | 对于该 URL,HTTP 方法已注册了控制器。 | 使用不同的 URL 或为另一个 HTTP 方法注册控制器。 | #2954 |
INVALID_URL | 路由器收到一个无效的 URL。 | 使用有效的 URL。 | #2106 |
ASYNC_CONSTRAINT_ERROR | 在使用异步约束时,路由器收到了错误。 | - | #4323 |
INVALID_URL_TYPE | URL 必须是字符串类型。 | 使用字符串类型的 URL。 | #3653 |
ROUTE_OPTIONS_NOT_OBJECT | 路由的选项必须是一个对象。 | 为路由选项使用一个对象。 | #4554 |
DUPLICATE_HANDLER | 不允许为路由设置重复的处理程序。 | 使用不同的处理程序。 | #4554 |
ROUTE_HANDLER_NOT_FUNCTION | 路由的处理程序必须是一个函数。 | 为处理程序使用一个函数。 | #4554 |
FST_ERR_ROUTE_MISSING_HANDLER | 路由缺少处理函数。 | 添加一个处理函数。 | #4554 |
FST_ERR_ROUTE_METHOD_INVALID | 方法不是有效值。 | 使用有效的值作为方法。 | #4750 |
FST_ERR_ROUTE_METHOD_NOT_SUPPORTED | 该方法不受路由支持。 | 使用受支持的方法。 | #4554 |
FST_ERR_ROUTE_BODY_VALIDATION_SCHEMA_NOT_SUPPORTED | 路由的主体验证模式不受支持。 | 使用不同的方法为该路由。 | #4554 |
FST_ERR_ROUTE_BODY_LIMIT_OPTION_NOT_INT | bodyLimit 选项必须是整数。 | 使用整数作为 bodyLimit 选项。 | #4554 |
FST_ERR_ROUTE_REWRITE_NOT_STR | rewriteUrl 需要为类型 string 。 | 使用字符串作为 rewriteUrl 。 | #4554 |
FST_ERR_REOPENED_CLOSE_SERVER | Fastify 已经被关闭,不能重新打开。 | - | #2415 |
FST_ERR_REOPENED_SERVER | Fastify 正在监听中。 | - | #2415 |
FST_ERR_PLUGIN_VERSION_MISMATCH | 已安装的 Fastify 插件与预期版本不符。 | 使用兼容版本的插件。 | #2549 |
FST_ERR_PLUGIN_CALLBACK_NOT_FN | 回调对于一个钩子来说不是一个函数。 | 使用函数作为回调。 | #3106 |
FST_ERR_PLUGIN_NOT_VALID | 插件必须是一个函数或一个 promise。 | 使用函数或 promise 作为插件。 | #3106 |
FST_ERR_ROOT_PLG_BOOTED | 根插件已经启动。 | - | #3106 |
FST_ERR_PARENT_PLUGIN_BOOTED | 由于父插件(直接从 avvio 映射)无法加载插件。 | - | #3106 |
FST_ERR_PLUGIN_TIMEOUT | 插件没有按时启动。 | 增加插件的超时时间。 | #3106 |
FST_ERR_PLUGIN_NOT_PRESENT_IN_INSTANCE | 装饰器不在实例中。 | - | #4554 |
FST_ERR_PLUGIN_INVALID_ASYNC_HANDLER | 注册的插件混合了异步和回调风格。 | - | #5141 |
FST_ERR_VALIDATION | 请求未通过有效负载验证。 | 检查请求的有效负载。 | #4824 |
FST_ERR_LISTEN_OPTIONS_INVALID | 监听选项无效。 | 检查监听选项。 | #4886 |
FST_ERR_ERROR_HANDLER_NOT_FN | 错误处理程序必须是函数 | 为 setErrorHandler 提供一个函数。 | #5317 |
FST_ERR_ERROR_HANDLER_ALREADY_SET | 错误处理程序已在当前作用域中设置。 设置 allowErrorHandlerOverride: true 以允许覆盖。 | 默认情况下,setErrorHandler 每个封装上下文只能调用一次。 | #6097 |