尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

深入解读 Hardhat 的错误体系:从 @nomicfoundation/hardhat-errors 到 HHE 错误码与版本演进

发布时间:2026/9/16 11:44:40

资讯中心
01
ARTICLE

深入解读 Hardhat 的错误体系:从 @nomicfoundation/hardhat-errors 到 HHE 错误码与版本演进

深入解读 Hardhat 的错误体系:从 @nomicfoundation/hardhat-errors 到 HHE 错误码与版本演进
深入解读 Hardhat 的错误体系从 nomicfoundation/hardhat-errors 到 HHE 错误码与版本演进【免费下载链接】hardhatHardhat is a development environment to compile, deploy, test, and debug your Ethereum software.项目地址: https://gitcode.com/GitHub_Trending/ha/hardhatnomicfoundation/hardhat-errors是 Hardhat 内部负责错误定义与错误码分配的核心组件它承载了HardhatError、HardhatPluginError、ErrorDescriptor等关键类型并维护着从HHE1到HHE120000的整套错误码清单。本文以该包 CHANGELOG.md 为主线结合 src/errors.ts 与 src/descriptors.ts 的源码实现系统讲解 Hardhat 3 的错误码格式、错误分类区间、消息模板机制并逐版本还原错误体系的演进轨迹。读完你将能读懂任意HHE开头的报错、定位其所属插件与分类并理解这些错误如何参与 Hardhat 的插件开发与排障流程。一、包定位Hardhat 内部的错误定义中枢按照 README.md 的说明这个包是Hardhat 的内部组件internal component不面向最终用户直接使用但它定义了 Hardhat 全体系使用的错误类与全部可能的错误列表。其模块对外导出四样东西HardhatError类——静态字段ERRORS上挂着它可接受的所有ErrorDescriptor错误描述符HardhatPluginError类——Hardhat 官方推荐的插件错误处理方式为方便起见同时从nomicfoundation/hardhat/plugins重新导出插件开发者应从这个路径导入ErrorDescriptor接口——描述一种错误应该长什么样assertHardhatInvariant断言助手。从 src/index.ts 可以看到包的公共出口只有这四个符号export type { ErrorDescriptor } from ./descriptors.js; export { HardhatError, HardhatPluginError, assertHardhatInvariant, } from ./errors.js;在包依赖层面package.json 表明它仅依赖nomicfoundation/hardhat-utils并且其exports额外暴露了./descriptors错误描述符模块和./package.json两个子路径——后者正是 CHANGELOG 3.0.13 中导出./package.json以便消费者读取包清单这一变更的实现落点。二、核心 API 源码级解读2.1 错误码前缀与格式HHE{number}在 src/errors.ts 中定义了前缀常量export const ERROR_PREFIX HHE;getErrorCode将描述符的编号与前缀拼接function getErrorCode(errorDescriptor: ErrorDescriptor): string { return ${ERROR_PREFIX}${errorDescriptor.number}; }于是每个错误的完整消息都是HHE{number}: {格式化后的消息模板}。测试用例 test/errors.ts 专门验证了这一格式it(should format the error code to 4 digits, () { const error new HardhatError(mockErrorDescriptor); assert.equal(error.message.substr(0, 8), HHE123: ); assert.equal( new HardhatError({ number: 1, messageTemplate: , /* ... */ }) .message.substr(0, 7), HHE1: , ); });也就是说HHE前缀 十进制编号编号不做补零处理HHE1、HHE27、HHE110003都是合法形式。2.2ErrorDescriptor一种错误的全套描述src/descriptors.ts 开头定义了ErrorDescriptor接口export interface ErrorDescriptor { /** 错误编号应保持全局唯一 */ number: number; /** 错误消息模板应尽量简短并告诉用户如何解决问题 */ messageTemplate: string; /** 为 true 时表示该错误应当被上报通常是内部 bug */ shouldBeReported?: true; /** 官网错误页使用的标题支持 markdown */ websiteTitle: string; /** 官网错误页使用的描述支持 markdown */ websiteDescription: string; }每个具体错误例如CORE.GENERAL.NOT_INSIDE_PROJECT都是一段这样的字面量对象ERRORS常量以包 → 分类 → 错误名三层结构组织并as const定型从而让 TypeScript 能在编译期推导出精确的错误编号和模板占位符类型。2.3HardhatError错误模板与类型安全的构造HardhatError的核心设计有四点值得注意。模板参数的类型级推导。通过模板字符串类型template literal typesMessageTemplateArguments会从messageTemplate里的{占位符}中自动提取参数名并推导出构造函数的第二个参数类型export type MessageTemplateArgumentsMessageTemplateT extends string MessageTemplateT extends ${string}{${infer Tag}}${infer Rest} ? { [K in Tag | keyof MessageTemplateArgumentsRest]: ErrorMessageTemplateValue } : {}; export type HardhatErrorConstructorArgumentsErrorDescriptorT extends ErrorDescriptor keyof MessageTemplateArgumentsErrorDescriptorT[messageTemplate] extends never ? [ErrorDescriptorT, Error?] : [ErrorDescriptorT, MessageTemplateArgumentsErrorDescriptorT[messageTemplate], Error?];也就是说如果模板没有占位符第二个参数是可选的原生Error作为 cause如果有占位符第二个参数必须是包含全部占位符键值的对象第三个参数才是 cause。test/errors.ts用expect-type对无变量、单变量、多变量、重复变量乃至{}空占位符等边界情况做了完整的类型测试。消息模板渲染。applyErrorMessageTemplate用正则/{.*?}/g把模板中的每个{tag}替换成传入值值为undefined→ 渲染为字符串undefined值为null→ 渲染为null值为bigint→ 渲染为123n带n后缀方便大整数可读值为数组 → 使用JSON.stringify其他对象 → 调用其toString()。伪私有标记代替instanceof。由于多个版本包可能并存instanceof不可靠构造器通过Object.defineProperty定义不可枚举、不可写的_isHardhatError属性isHardhatError静态方法读取该属性并可选地校验number是否匹配某个描述符。HardhatPluginError采用同样的_isHardhatPluginError机制。测试中对HardhatError、HardhatPluginError、普通Error、null、undefined、数字、字符串、普通对象互相判别的场景都有覆盖。pluginId的动态推导。pluginIdgetter 遍历ERROR_CATEGORIES找到包含当前descriptor.number的包区间并返回其pluginIdCORE 区间的pluginId为undefined属于 Hardhat 本体。测试里以HARDHAT_KEYSTORE的错误验证了该逻辑。2.4HardhatPluginError给社区插件作者的推荐用法export class HardhatPluginError extends CustomError { constructor( public readonly pluginId: string, message: string, parentError?: Error, ) { ... } }它接收插件 ID、普通消息文本和可选的父错误不参与HHE编号体系——因为它面向第三方插件的错误而HHE编号体系主要由官方组件占用。README 明确建议插件开发者应从nomicfoundation/hardhat/plugins导入该错误类型。2.5assertHardhatInvariant内部不变式断言export function assertHardhatInvariant( invariant: boolean, message: string, ): asserts invariant { if (!invariant) { throw new HardhatError(ERRORS.CORE.INTERNAL.ASSERTION_ERROR, { message }); } }当内部条件被违反时抛出编号为100的HHE100: An internal invariant was violated: {message}错误。该错误在描述符中被标记为shouldBeReported: true配合CORE.INTERNAL.NOT_IMPLEMENTED_ERRORHHE101一起构成这是 Hardhat 自身的 bug请上报的语义通道。在 Hardhat 主包源码中coverage 插件的 instrumentation.ts、gas-analytics 插件的 accessors.ts 等处都大量使用了assertHardhatInvariant。三、错误码分区ERROR_CATEGORIES的编号宇宙ERROR_CATEGORIES是错误码命名空间的顶层索引。每个包如CORE、IGNITION、HARDHAT_VERIFY占据一个互不重叠的编号区间区间内再按CATEGORIES细分。HardhatError#pluginId正是借助这些区间完成错误码 → 插件的反查。整体编号分配如下包区间pluginId典型分类CORE1 – 9999无Hardhat 本体GENERAL 1–99、INTERNAL 100–199、PLUGINS 200–299、HOOKS 300–399、TASK_DEFINITIONS 400–499、ARGUMENTS 500–599、BUILTIN_TASKS 600–699、NETWORK 700–799、SOLIDITY_TESTS 800–899、SOLIDITY 900–999、ARTIFACTS 1000–1099、NODE 1100–1199、TEST_PLUGIN 1200–1299、COVERAGE 1300–1399、INIT 1400–1499IGNITION10000 – 19999hardhat-ignitionGENERAL 10000–10099、INTERNAL 10100–10199、MODULE 10200–10299、SERIALIZATION 10300–10399、EXECUTION 10400–10499、RECONCILIATION 10500–10599、WIPE 10600–10699、VALIDATION 10700–10799、STATUS 10800–10899、DEPLOY 10900–10999、VERIFY 11000–11099、STRATEGIES 11100–11199、LIST_TRANSACTIONS 11200–11299、TRACK_TRANSACTIONS 11300–11399HARDHAT_ETHERS20000 – 29999hardhat-ethersGENERAL 20000–20099HARDHAT_MOCHA30000 – 39999hardhat-mochaGENERAL 30000–30099HARDHAT_VIEM40000 – 49999hardhat-viemGENERAL 40000–40099HARDHAT_KEYSTORE50000 – 59999hardhat-keystoreGENERAL 50000–50099NETWORK_HELPERS60000 – 69999hardhat-network-helpersGENERAL 60000–60099CHAI_MATCHERS70000 – 79999hardhat-ethers-chai-matchersGENERAL 70000–70099HARDHAT_VERIFY80000 – 89999hardhat-verifyGENERAL 80000–80099、VALIDATION 80100–80199HARDHAT_LEDGER90000 – 90999hardhat-ledgerGENERAL 90000–90099HARDHAT_FOUNDRY100000 – 109999hardhat-foundryGENERAL 100000–100099HARDHAT_SLANG_SOLX110000 – 119999hardhat-slang-solxGENERAL 110000–110099HARDHAT_NODE_TEST_RUNNER120000 – 129999hardhat-node-test-runnerGENERAL 120000–120099这样的区间划分让根据错误码快速定位所属插件/子系统成为可能看到HHE80001就知道问题出在 hardhat-verify 与区块浏览器的交互上看到HHE10400就直奔 Ignition 的执行层。四、编号纪律测试如何守护错误码不混乱错误码的稳定性对生态至关重要因此 test/errors.ts 用 node:test 写了几条硬性纪律每个区间的min max防止倒置包区间互不重叠、分类区间互不重叠且分类区间必须完整落在所属包区间之内每个已注册错误的编号必须在分类区间内上限为max - 1因为max是开放的边界编号不得重复同一分类内编号必须连续、无空洞从min起逐号递增任何分类不得为空。这些测试从机制上保证了新增错误只能追加、不能破坏既有编号也解释了为什么 CHANGELOG 里出现HHE27、HHE110003、HHE110004这样的跳号——它们各自落在对应分类区间内且顺序追加。五、版本演进从 3.0.0 到 3.0.21 的功能时间线以下以 CHANGELOG.md 为骨架逐版本梳理错误体系伴随 Hardhat 3 一起演进的轨迹。5.1 3.0.0 —— Hardhat 3 首发Major ChangeFirst release of Hardhat 3!。这是错误包随 Hardhat 3 全新发布HHE错误码体系自此成为 Hardhat 3 的标准错误语言。5.2 3.0.1 3.0.4 —— 基础能力补全3.0.1新增守卫阻止ignition.deploy(...)被并发多次调用——对应 IGNITION 分类HHE10901 ALREADY_IN_PROGRESS3.0.2① 在于本地仓库中使用全局安装的 Hardhat时报错HHE22 NON_LOCAL_INSTALLATION错误消息要求改用 pnpm/npm/yarn 本地安装② 支持自定义编译器HHE918 BUILD_INFO_COMPILER_TYPE_NOT_HANDLED等相关描述符随之出现意味着非 solc 编译器类型需要插件注册 handler3.0.3将nomicfoundation/hardhat-ledger移植到 Hardhat 3LEDGER 区间 90000 的错误随之纳入3.0.4当某个文件既不被识别为合约也不被识别为测试时构建失败——即HHE915 UNRECOGNIZED_FILES_NOT_COMPILEDSolidity 测试文件必须放在 test 目录或在 contracts 目录且以.t.sol结尾。5.3 3.0.5 3.0.9 —— 面向网站的导出与测试工具链3.0.5向官网导出错误描述符websiteTitle/websiteDescription字段存在的意义正在于此并把文档长链接替换为带跳转的短链接3.0.6任务选项支持从 CLI 隐藏对应HHE512 NO_HIDDEN_OPTION_CLI隐藏选项只能编程使用3.0.7① 升级 hardhat-utils② 引入nomicfoundation/hardhat-foundry插件FOUNDRY 区间 100000HHE100000 FORGE_NOT_INSTALLED提示检查 Foundry 是否安装、forge是否在 PATH③ 任务支持inline actions在任务定义中直接写setInlineAction对应HHE417、HHE418、HHE419三条约束描述符3.0.8Solidity 测试支持函数级 gas 快照与快照 cheatcode通过--snapshot与--snapshot-check两个标志启用配套HHE803~HHE806的 snapshot 文件读写与互斥标志错误3.0.9①network.createServer(...)增加对http网络配置的防护HHE724 CREATE_SERVER_UNSUPPORTED_NETWORK_TYPE只有edr-simulated网络可创建本地 JSON-RPC 服务器② 新增全局选项--gas-stats-json path把 gas 用量统计写入 JSON 文件。5.4 3.0.10 3.0.13 —— 配置钩子与项目初始化3.0.10① Solidity 测试支持按测试函数内联配置forge-config:/hardhat-config:NatSpec 注释早期形态对应HHE807~HHE813一组合法键、重复键、非法值、非法语法等描述符② 引入ConfigHooks#validateResolvedConfig钩子与HardhatConfigValidationError类型可对解析后的配置做全局校验——对应HHE24 INVALID_RESOLVED_CONFIG3.0.11① 不再上报并非 bug的 HardhatErrorshouldBeReported机制的意义② 包从仓库根移入packages/目录③hre.network.connect()弃用改用语义更明确的hre.network.create()④ 合约与 Solidity 测试的分开编译变为可选由新配置字段splitTestsCompilation控制false时两者同以scope: contracts编译对应HHE916 SPLIT_TESTS_COMPILATION_DISABLED⑤ Breaking change移除hardhat.config.ts中 Solidity 测试的timeout配置项旧HHE801 RUNNER_TIMEOUT被标记为废弃3.0.12改进常见失败场景的错误消息3.0.13① 为 Solidity Test cheatcode 暴露的重复 EIP-712 结构体名新增错误描述符HHE818 EIP712_DUPLICATE_STRUCT_NAME②导出./package.json子路径③--init --template template-name非交互式初始化项目以及--init --templates列出可用模板——配套HHE16 TEMPLATE_NOT_FOUND、HHE25、HHE26 NON_INTERACTIVE_INIT_WOULD_OVERWRITE_FILES、HHE513等描述符。5.5 3.0.14 3.0.17 —— 正确性修复3.0.14修复hardhat flatten在 Solidity 循环依赖下静默产出误导性输出的问题——HHE602 FLATTEN_CYCLIC_DEPENDENCY明确告知 flatten 依赖拓扑排序有环则无拓扑序需要重构源码消除循环导入3.0.15当区块浏览器报告构造参数不正确时hardhat verify更快失败3.0.16nonce 校验处理 mempool 延迟——校验前先重试避免陈旧 pending 计数误报对应HHE10404 INVALID_NONCE、HHE10411 NONCE_TOO_HIGH、HHE10412 NONCE_TOO_LOW等 Ignition 执行层错误3.0.17修复 EIP-712 收集器对用户未包含的源文件中同名结构体误抛的 bug同时升级hardhat-utils4.1.5。5.6 3.0.18 3.0.21 —— 测试过滤、容差与原生绑定3.0.18支持测试名过滤取反--grep-excludeSolidity 与 Mocha 测试均可配套HHE30001~HHE30004一组 Mocha 区间的兼容性与正则合并错误描述符以及HHE120000 GREP_EXCLUDE_NOT_SUPPORTEDnode:test runner 因隔离模式限制不支持取反直接拒绝而非静默忽略3.0.19① 为nomicfoundation/edr或nomicfoundation/solidity-analyzer的原生绑定加载失败新增检测与专属错误HHE27 NATIVE_BINDING_LOAD_FAILED消息里给出 npm 可选依赖 bug 的完整修复步骤升级 npm ≥ 11.3.0、删除node_modules与 lockfile 后重装② Solidity 测试的--snapshot-check新增--tolerance选项允许快照值按百分比漂移后才判定失败配套HHE819 SNAPSHOT_TOLERANCE_REQUIRES_CHECK--tolerance只能与--snapshot-check联用与HHE820 INVALID_SNAPSHOT_TOLERANCE要求非负有限数值3.0.20为hardhat-slang-solx插件新增HHE110003无法获取 solx 二进制校验和与HHE110004下载的 solx 二进制与校验和不匹配补全 SLANG_SOLX 区间3.0.21将 Solidity 测试运行中的内联配置解析移植到 Rust显著提升编译速度3.0.10 引入的内联配置功能在 3.0.21 完成了性能优化落地。5.7 依赖同步节奏CHANGELOG 还揭示了一个重要工程事实hardhat-errors与hardhat-utils保持同步升级。3.0.12→3.0.17 分别联动hardhat-utils4.1.0/4.1.2/4.1.3/4.1.4/4.1.53.0.7 还专门有一条 Bumphardhat-utilsmajor。这是因为HardhatError/HardhatPluginError都继承自nomicfoundation/hardhat-utils/error的CustomErrorapplyErrorMessageTemplate也依赖 utils 的工具函数两者共享同一套错误底座。六、在真实排障中的应用掌握这套体系后面对一条HHE报错可以按三步定位读前缀之后的编号对照上文的分区表确定归属HHE1~HHE9999是 Hardhat 核心HHE10000属于 IgnitionHHE80000属于 verify 插件HHE110000属于 solx 编译器看pluginIdHardhatError#pluginId会基于编号区间直接告诉你应该去哪个插件仓库排查看消息模板与shouldBeReported若错误描述符标了shouldBeReported: true如HHE100、HHE101、HHE802说明这是 Hardhat 或插件自身的 bug应当上报而不是自行绕过其余错误消息通常已经写明修复建议——例如HHE22提示本地安装、HHE27提示升级 npm 后重装依赖、HHE915提示把测试文件放到正确位置并以.t.sol结尾。对插件开发者而言推荐的做法是属于 Hardhat 本体或官方插件的行为使用HardhatErrorERRORS中已有的描述符自定义插件的业务失败使用HardhatPluginError从nomicfoundation/hardhat/plugins导入并传递清晰的pluginId让使用者在错误堆栈和官网文档之间建立起可追溯的关联。七、结语nomicfoundation/hardhat-errors虽是一个不面向终端用户的内部包却定义了 Hardhat 3 全部用户可感知错误的语法。通过本文梳理的HHE前缀、ErrorDescriptor五元组、ERROR_CATEGORIES区间编号纪律以及 CHANGELOG.md 呈现的 3.0.0→3.0.21 演进过程你可以把一条冰冷的错误码还原为一段可查证、可定位、可修复的开发上下文——这正是 Hardhat 精心设计这套错误体系的价值所在。【免费下载链接】hardhatHardhat is a development environment to compile, deploy, test, and debug your Ethereum software.项目地址: https://gitcode.com/GitHub_Trending/ha/hardhat创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。