深入理解 Dagger TypeScript SDK 的 ErrorID:错误对象唯一标识符的类型定义与实战解析
深入理解 Dagger TypeScript SDK 的 ErrorID错误对象唯一标识符的类型定义与实战解析【免费下载链接】daggerAutomation engine to build, test and ship any codebase. Runs locally, in CI, or directly in the cloud项目地址: https://gitcode.com/GitHub_Trending/da/dagger本篇技术指南围绕 Dagger 引擎自动化构建、测试与交付任意代码库的自动化引擎TypeScript SDK 中的ErrorID类型别名展开系统讲解它在client.gen代码生成体系中的定义方式、string object交叉类型的语义以及它如何与Error、ErrorValue对象和 GraphQL 的loadErrorFromID查询协同工作。读完本文你将掌握 Dagger TypeScript SDK 中错误对象 ID 的类型规则、生成代码的实现形态以及如何在 Dagger 模块中创建、扩展、持久化与按 ID 恢复错误对象。关联文档定位本文核心依据是版本化文档 ErrorID.md位于 Dagger 0.21 版 TypeScript SDK API 参考的client.gen/type-aliases目录下该目录存放的是由 Dagger 代码生成器自动产出的 TypeScript SDK 类型别名文档与仓库中的 client.gen.ts 一一对应。ErrorID 是什么类型别名定义按照原文档ErrorID的定义如下type ErrorID string object文档给出的语义说明为A unique identifier for an object.对象唯一标识符并在 Type Declaration 一节声明了一个名为__ErrorID、类型为never的标记属性interface ErrorID { __ErrorID: never }也就是说ErrorID并不是普通的string而是一个名义类型nominal / branded type它以字符串为载体但同时带有一个不可赋值的never标记属性从而在类型系统层面把任意字符串和Error 对象的 ID区分开防止开发者误把普通字符串直接当作对象 ID 传入 API。与 ID 及其他对象 ID 的关系在client.gen/type-aliases目录下这种定义模式被所有对象 ID 类型共用ID.md、ErrorValueID.md、ContainerID、DirectoryID、ServiceID等几十个类型全部采用string object加never标记的写法。ErrorID是这一整套 ID 类型体系中的一员专门标识Error对象。在生成的 Go 侧代码中可以看到更直接的对齐关系sdk/typescript/runtime/internal/dagger/dagger.gen.go第 203 行定义了type ErrorID string而 Go 模块测试样板core/integration/testdata/modules/go/defaults/foobar/internal/dagger/dagger.gen.go第 200 行则写成type ErrorID ID说明在 SDK 生成层ErrorID与通用ID是同一类型的别名TypeScript 侧之所以保留独立别名是为了让 API 签名具备语义化的自文档能力。ErrorID 背后的对象体系Error 与 ErrorValueErrorID是Error对象的身份证。要理解它必须同时看清它服务的两个对象类及其全部方法。Error 类参考 classes/Error.md 与 client.gen.ts 中的实现Error对象提供方法签名说明id()PromiseID返回该 Error 对象的唯一标识符即ErrorID的底层值message()Promisestring返回错误描述文本values()PromiseErrorValue[]返回错误的扩展值列表GraphQL 语义中的 extensionswithValue(name, value)(name: string, value: JSON) Error向错误对象追加一个命名扩展值返回新的Error实例with(arg)(arg: (param: Error) Error) Error把当前 Error 传入回调便于复用与保持调用链可读性注意构造器签名new Error(ctx?, _id?, _message?)文档明确标注Constructor is used for internal usage only, do not create object from it——Error对象只能通过Client.error()等引擎入口创建不应直接实例化。ErrorValue 类参考 classes/ErrorValue.md 与 client.gen.ts 起对应实现每个扩展值是一个ErrorValue对象同样具有自己的 IDErrorValueID方法返回说明id()PromiseIDErrorValue 的唯一标识符name()Promisestring扩展值的名称value()PromiseJSON扩展值的具体内容JSON 类型创建与加载Client 上的三个关键入口ErrorID的生成与消费都发生在 Client 类 上对应 GraphQL 查询在 base_schema.graphqls 中有完整定义。创建错误error()client.error(message: string): ErrorGraphQL 层error(message: String!): Error!注释为 Create a new error.实现层core/schema/error.go中errorSchema.error接收Message参数返回core.Error{Message: args.Message}并给 span 打上telemetry.UIInternalAttr标记使该类错误不会出现在 UI 界面中仅作为内部对象传递。参数说明message为必填字符串是 A brief description of the error.。按 ID 加载loadErrorFromID() / loadErrorValueFromID()client.loadErrorFromID(id: ErrorID): Error client.loadErrorValueFromID(id: ErrorValueID): ErrorValueGraphQL 层定义见 base_schema.graphqlsLoad a Error from its ID. loadErrorFromID(id: ErrorID!): Error! Load a ErrorValue from its ID. loadErrorValueFromID(id: ErrorValueID!): ErrorValue!生成的 TypeScript 客户端与 Go 运行时行为一致sdk/typescript/runtime/internal/dagger/dagger.gen.go#L12936-L12954中LoadErrorFromID/LoadErrorValueFromID把 ID 作为id参数拼入loadErrorFromID/loadErrorValueFromIDGraphQL 选择集并返回对应客户端句柄。这意味着ErrorID是一个可持久化、可序列化、可跨会话恢复的句柄值你先通过id()拿到它之后无论在同一个 Dagger 会话还是持久化缓存加载路径中都可以用它重新定位到同一个错误对象。源码级原理Error 的持久化与 ID 生成核心模型core/error.go定义了引擎侧的错误模型type Error struct { Message string field:true doc:A description of the error. Values []*ErrorValue field:true doc:The extensions of the error. }关键事实core/error.goError实现了dagql.PersistedObject与dagql.PersistedObjectDecoder具备EncodePersistedObject/DecodePersistedObject能力可被编码为 JSON 载荷存入持久化缓存也可从载荷解码还原Error同时实现了标准error接口Error()返回Message与dagql.ExtendedError接口Extensions()把Values列表还原为map[string]any供 GraphQL extensions 语义使用ErrorValue结构体由Name string与Value JSON组成同样实现了持久化编解码WithValue(name, value)采用不可变追加策略先Clone()再追加新值返回新对象因此Error实例可以被安全地链式扩展而互不影响。ID 从哪来ErrorID本身不承载业务信息它是Error对象在 dagql 服务器中计算结果的身份句柄。dagql 框架对所有可持久化对象统一处理dagql/cache_persistence_self.go中PersistedObjectDecoder.DecodePersistedObject负责按 ID/载荷还原对象dagql/cache_persistence_resolver.go#L281的LoadPersistedObjectByResultID负责从持久化结果 ID 加载对象。因此ErrorID是这一通用对象 ID 机制在错误类型上的具体化。引擎内部如何把 Go error 变成 Dagger Errorcore/error.go#L29-L81的NewErrorFromErr展示了 ID 生态的入口逻辑当引擎内部发生错误时如果错误实现了dagql.ExtendedError会先构造error(message)选择集再对扩展值按键排序逐个追加withValue(name, value)选择集最后通过srv.Select在 dagql 服务器上执行把 Go 错误完整地转成带扩展值的 DaggerError对象——每个扩展值都是独立可寻址的ErrorValue也就拥有独立的ErrorValueID。实战场景在 Dagger 模块中产生带扩展值的错误ErrorID最典型的落地场景是 Dagger 模块的异常处理。看 entrypoint.ts 中formatError的实现function formatError(e: unknown): DaggerError { if (e instanceof Error) { let error dag.error(e.message) // 如果是 ExecError 或 GraphQLRequestError把 extensions 作为扩展值写入错误 if (e instanceof ExecError || e instanceof GraphQLRequestError) { Object.entries(e.extensions ?? []).forEach(([key, value]) { if (value ! value ! undefined value ! null) { error error.withValue(key, JSON.stringify(value) as JSON) } }) } return error } try { return dag.error(JSON.stringify(e)) } catch { return dag.error(String(e)) } }要点拆解模块入口把用户抛出的异常统一转换为 DaggerError对象先dag.error(message)创建基础错误再对ExecError/GraphQLRequestError的extensions逐项调用withValue写入扩展值withValue的value参数类型是JSON即JSONValue因此传入前需要用JSON.stringify序列化最终错误对象经引擎处理后message、values乃至各自的ErrorID/ErrorValueID都会进入 dagql 结果缓存可以被id()获取、被loadErrorFromID(id)在后续查询中恢复也可随持久化缓存跨会话保留。使用建议与注意事项不要把ErrorID当普通字符串处理由于它是string object的品牌类型直接传普通字符串字面量会触发类型错误必须先通过error.id()异步或从loadErrorFromID等 API 获取符合类型的值。这虽然带来一点类型样板但能在编译期拦截拿错 ID这类错误。ID 是句柄而非内容ErrorID不含消息文本或扩展值业务数据要通过message()与values()读取对象本身则以 JSON 载荷形式持久化见core/error.go的编解码实现。优先使用withValue携带结构化扩展信息相比把全部信息拼进message字符串扩展值以 JSON 保存、按键名访问机器可解析且与 GraphQL extensions 语义对齐。版本注意本文内容基于仓库docs/versioned_docs/version-0.21版本化文档及当前主分支源码client.gen为代码生成产物若升级 Dagger 版本请以对应版本重新生成的类型文档为准。小结ErrorID是 Dagger TypeScript SDK 中错误对象唯一标识符的语义化类型别名定义为string object并携带__ErrorID: never名义标记。它串联起三条主线类型层面client.gen.ts生成的品牌字符串类型、对象层面Error/ErrorValue及其id、message、values、withValue等方法、引擎层面core/error.go 中Error的持久化编解码、core/schema/error.go 的error/withValueGraphQL 解析器以及loadErrorFromID查询。理解ErrorID也就理解了 Dagger 中对象—ID—持久化—恢复这一核心数据通路在错误处理上的完整实现。【免费下载链接】daggerAutomation engine to build, test and ship any codebase. Runs locally, in CI, or directly in the cloud项目地址: https://gitcode.com/GitHub_Trending/da/dagger创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

拿 Claude Chat 拉取素材,TaoToken 只提供 Key 和 Base URL

拿 Claude Chat 拉取素材,TaoToken 只提供 Key 和 Base URL

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/21 4:28:04 阅读更多 →
FPGA实现UDP协议栈:verilog-ethernet开源工程学习与上板调试

FPGA实现UDP协议栈:verilog-ethernet开源工程学习与上板调试

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/20 22:43:53 阅读更多 →
零知识机器学习(zkML)原理与实战:从模型到可验证推理的完整链路

零知识机器学习(zkML)原理与实战:从模型到可验证推理的完整链路

零知识机器学习这几年在链上AI、隐私计算圈子里确实火得厉害,但市面上讲概念的多、讲实操的少。我前前后后跑了几个zKML相关的验证流程,也踩了一些坑,今天就把这块从原理到落地的完整链路掰开揉碎讲清楚,给后面想入坑的朋友省点时…

2026/9/20 17:13:51 阅读更多 →

最新新闻

文字扫描识别软件面试避坑:3个核心考点助你搞定性能优化

文字扫描识别软件面试避坑:3个核心考点助你搞定性能优化

文字扫描识别软件面试避坑:3个核心考点助你搞定性能优化 很多开发者学了 OCR 基础语法,却卡在“怎么把识别准确率提到 99% 以上”这一步。别慌,这正是面试大厂时最容易被问到的 性能优化…

2026/9/22 2:26:20 阅读更多 →
车架号查询车辆信息实战:5种后端方案对比与最佳实践

车架号查询车辆信息实战:5种后端方案对比与最佳实践

车架号查询车辆信息实战:5种后端方案对比与最佳实践 学会语法却不知怎么搭项目?这是很多开发者从教程走向生产环境时最大的拦路虎。尤其是面对像 车架号查询车辆信息 这种典型的高频业务场景,很多人只会写 SELECT * FROM cars…

2026/9/22 2:26:20 阅读更多 →
沪深300指数源码解析:3步吃透指数计算与回测框架

沪深300指数源码解析:3步吃透指数计算与回测框架

沪深300指数源码解析:3步吃透指数计算与回测框架 面试被问原理答不上来,这是很多量化新人的噩梦。当你自信满满地说“我会Python”,面试官追问“沪深300指数的加权方式具体怎么在代码里实现?处理复权因子有坑吗?”时,瞬间大脑空白。这种尴…

2026/9/22 2:26:20 阅读更多 →
控制近义词踩坑实录

控制近义词踩坑实录

搞懂控制流:从报错到源码解析的避坑指南 屏幕上的红色 StackTrace 像一堵墙,把你死死堵在调试界面。你盯着那行 Uncaught TypeError…

2026/9/22 2:25:19 阅读更多 →
枪破兑换码性能优化:新手避坑指南

枪破兑换码性能优化:新手避坑指南

枪破兑换码性能优化:新手避坑指南 学会语法却不知怎么搭项目,这是很多开发者入行时的第一道坎。很多人盯着教程里的代码敲了一遍又一遍,觉得自己懂了,真到了公司项目里,面对海量请求和高并发场景,瞬间就懵了。 这时候, 性能优化…

2026/9/22 2:25:19 阅读更多 →
C指针性能优化实战:3招解决栈溢出,附速查手册

C指针性能优化实战:3招解决栈溢出,附速查手册

C指针性能优化实战:3招解决栈溢出,附速查手册 刚接手一个老旧的C项目,打开IDE运行,屏幕瞬间被红色的报错信息淹没。Stack Trace…

2026/9/22 2:25:19 阅读更多 →

日新闻

3台商务办公笔记本实测:手写实现环境配置,告别卡半天

3台商务办公笔记本实测:手写实现环境配置,告别卡半天

3台商务办公笔记本实测:手写实现环境配置,告别卡半天 配置环境就卡半天?别怪机器慢,多半是你没选对工具链。在Java、Go或Python的项目现场, 手写实现…

2026/9/22 0:00:41 阅读更多 →
剑帝加点速查手册:3分钟搞懂核心逻辑

剑帝加点速查手册:3分钟搞懂核心逻辑

剑帝加点速查手册:3分钟搞懂核心逻辑 面试被问原理答不上来,是不是常态?别慌。很多开发者对着 GitHub 开源仓库里的代码发呆,看似简单实则暗藏玄机。今天这份【剑帝加点】速查手册,直接带你拆解核心实现,把面试必考的原理讲透。…

2026/9/22 0:00:41 阅读更多 →
手写实现图片压缩网站核心:搞定WebP转换与质量调优

手写实现图片压缩网站核心:搞定WebP转换与质量调优

手写实现图片压缩网站核心:搞定WebP转换与质量调优 复制来的代码跑不通不知道怎么调?别慌,这种“复制粘贴地狱”在开发圈太常见了。尤其是做 图片压缩网站…

2026/9/22 0:00:41 阅读更多 →

周新闻

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

直接铺开项目本身吧。这几个月我一直在折腾一件事:用Flutter给OpenHarmony做一款游戏集合类的App,说白了就是把若干小游戏塞进一个壳里,用统一入口分发。这个方向本身不算新鲜,真正让我花了不少心思的,是首页那堆游戏卡…

2026/9/21 3:13:20 阅读更多 →
Word表格编号全攻略:从列表编号到题注交叉引用

Word表格编号全攻略:从列表编号到题注交叉引用

写Word文档,最让人头疼的往往是那些“看起来不起眼”的小问题。比如表格编号这事:今天在表后面多加了两个空白行,明天给客户交稿前发现整个章节的编号全部错位,光是挨个改序号就能耗掉大半个下午。我前阵子帮人整理一份上百页的技…

2026/9/21 2:19:36 阅读更多 →
从第一个站到第二个站:独立开发者的静态网站选型与落地实践

从第一个站到第二个站:独立开发者的静态网站选型与落地实践

1. 项目概述1.1 核心需求解析做独立开发者这几年,说实话,第一个网站上线的那天晚上我兴奋得没睡着。但等它跑了半年,流量惨淡、功能臃肿、代码自己都懒得看第二遍之后,我才慢慢琢磨明白一个道理:第一个网站是练手&…

2026/9/21 4:51:05 阅读更多 →

月新闻

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

2026/9/21 15:36:51 阅读更多 →
容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…

2026/9/21 15:36:51 阅读更多 →
容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步分类:[工程技术]细分主题:Docker 容器化技术与镜像安全管理:核心链路的逐步实现与关键代码取舍面对一个积累了五六年历史包袱的单体架构应用(包含 Web 接口、后台…

2026/9/19 23:35:34 阅读更多 →