错误报告
deno desktop 随 Deno v2.9.0 一并发布,但目前尚未进入稳定版。要立即试用,请运行 deno upgrade canary 以安装
canary 构建版本。在该功能稳定之前,命令、配置键以及 TypeScript API 仍可能发生变化。
deno desktop 应用会自动捕获:
- Deno 端代码和渲染端代码中的未捕获 JavaScript 异常。
- 未处理的 promise 拒绝。
- 运行时或渲染后端中的 Rust panic。
当其中之一发生时,运行时会显示一个带有错误消息的原生警报;如果你配置了报告 URL,则会 POST 一份 JSON 报告。
配置 Jump to heading
在你的 deno.json 中设置 desktop.errorReporting.url:
{
"desktop": {
"errorReporting": {
"url": "https://errors.example.com/report"
}
}
}
该 URL 必须使用 https:// 或 file://。纯 http:// 会被拒绝,因为报告会携带堆栈信息和运行时上下文,路径中的任何人都可能读取。file:// URL 适用于本地测试:运行时会将 JSON 追加到该路径,而不是发出 HTTP 请求。
如果没有设置 errorReporting.url,警报仍然会出现,但不会发送报告。
报告格式 Jump to heading
{
"version": 1,
"message": "TypeError: Cannot read properties of null",
"stack": "TypeError: Cannot read properties of null (reading 'foo')\n at handler (file:///main.ts:12:14)\n at …",
"appVersion": "1.4.0",
"timestamp": "2026-04-08T12:00:00.000Z",
"platform": "darwin",
"arch": "aarch64"
}
| 字段 | 类型 | 说明 |
|---|---|---|
version |
1 |
规范版本。请在服务器端检查此值。 |
message |
string |
错误的 message。 |
stack |
string |
错误的 stack。在可能的情况下会进行源映射。 |
appVersion |
string | null |
错误发生时的 Deno.desktopVersion。 |
timestamp |
ISO 8601 string | 捕获到错误时的 UTC 时间戳。 |
platform |
"darwin" | "windows" | "linux" |
Deno.build.os。 |
arch |
string | Deno.build.arch。 |
Content-Type 头为 application/json。报告会以单次 POST 发送,不会重试。如果你的服务器宕机,报告就会丢失。对于高重要级别的报告,请在本地排队并在下次启动时重新发送。
会被报告的内容 Jump to heading
| 来源 | 是否捕获? |
|---|---|
| Deno 端代码中的未捕获异常 | 是。 |
| Deno 端代码中的未处理拒绝 | 是。 |
| 渲染端 JS 中的未捕获异常 | 是;通过渲染器的 error 事件捕获。 |
| Deno 运行时中的 Rust panic | 是。 |
| 渲染后端(CEF,…)中的 Rust panic | 是;后端会桥接这些 panic。 |
console.error / console.warn |
否;这些不是错误。 |
你自己通过 try/catch 处理的异常 |
否。 |
在 binding 处理器中抛出的错误会传播到 webview 端,并使调用它的 promise 被拒绝。它们不会作为未捕获错误被报告;webview 会捕获它们。若仍想报告它们,请在 binding 处理器中自行记录。
抑制警报 Jump to heading
该警报旨在在出错时让用户知情。它会针对每一个未捕获错误、未处理拒绝和 panic 触发,目前没有办法从用户代码中将其抑制:运行时会在你的代码运行之前注册其 error 和 unhandledrejection 处理器,因此你稍后添加的监听器中的 preventDefault() 不会停止警报或报告。
要避免某个错误触发警报,就要阻止它成为未捕获错误:在你的代码和 binding 实现中使用 try/catch(或本地错误处理)来处理它:
win.bind("readFile", async (path) => {
try {
return await Deno.readTextFile(path);
} catch (e) {
reportToOwnTelemetry(e);
return null; // 已处理,不会警报
}
});
你仍然可以添加自己的 error / unhandledrejection 监听器来获取额外遥测;它们会在内置处理器之后运行,并与警报和报告并行:
addEventListener("error", (e) => reportToOwnTelemetry(e.error));
addEventListener("unhandledrejection", (e) => reportToOwnTelemetry(e.reason));
服务器端示例 Jump to heading
一个最小的报告接收器:
Deno.serve({ port: 8080 }, async (req) => {
if (req.method !== "POST") return new Response(null, { status: 405 });
const report = await req.json();
if (report.version !== 1) {
return new Response("不支持的版本", { status: 400 });
}
await Deno.writeTextFile(
`./reports/${report.timestamp}.json`,
JSON.stringify(report, null, 2),
);
return new Response(null, { status: 204 });
});
在生产环境中,你会将其写入数据库,或转发到合适的崩溃收集服务。
隐私注意事项 Jump to heading
默认报告包含 stack 堆栈跟踪,其中可能包含嵌入在错误消息中的用户数据(文件名、URL、查询参数、序列化的对象字段)。如果你的应用处理敏感数据,请考虑:
- 在发送前从堆栈帧中移除参数。
- 对
Deno.readTextFile调用及类似内容的 URL 进行脱敏。 - 在发送第一份报告前先询问用户(一次性的同意提示)。
这些都是应用层面的决定;内置报告器会发送它所拥有的内容,其负载无法从用户代码中被过滤。若要完全控制离开机器的数据,请不要设置 errorReporting.url,而是改为在 error / unhandledrejection 处理器中发送你自己的报告。