常见坑
每一章对着一个报错或一个现象:先用最小的程序把它复现出来(输出是 M2 Max、macOS 27、rustc 1.99.0 上 tauri 2.12.5 的原文,窗口一律隐藏),再到源码里找它从哪一行来,最后给出修法和检查办法。机制在前面几部分讲过的,这里只链过去,不再重复。有几个坑是 tauri 自己的问题,章里写明在哪个版本上复现。Windows 和 Linux 上的差异只读了源码,章里另外标出。
- 开发模式启动后 bus error 退出:开发模式在第一次
Ready时用 ImageIO 解码应用图标,DYLD_LIBRARY_PATH指向 Homebrew 时加载了另一份 libpng,进程无声退出。 - does not match the allowlist defined under tauri.conf.json:
tauri依赖的 features 和配置推出的 feature 要逐字一致,经自己的[features]间接打开也算缺失。 - failed to open icon:
generate_context!编译期要一张 RGBA 的 PNG 图标,缺了或格式不对,过程宏 panic。 - 每次 cargo build 都重编整个应用:没有
capabilities/目录时 cargo 每次都认为它变了;反过来往frontendDist新加的文件不会触发重编。 - generate_context! 读的不是你指定的配置文件:只用配置路径的目录,文件名被忽略,读的总是
tauri.conf.json。 - command greet missing required key userName:参数键是 lowerCamelCase,只管顶层;嵌套字段按各自的 serde 属性,数组直接传会变成字节。
- async commands that contain references as inputs must return a
Result:async 命令借用参数时要返回Result,根子在 future 的'static约束。 - state not managed for field
counteron commandhit:状态按TypeId存取,manage(Counter)和State<Mutex<Counter>>是两种类型;Builder上重复manage直接 panic。 - a webview with label
mainalready exists:窗口和 webview 标签各自唯一;setup里用?传出这个错误会让进程 abort。 - 一个同步命令,别的请求全在等:同步命令在主线程上执行,期间别的 invoke、
tauri://资源、窗口操作都要等;改成 async。 - failed to initiate panic, error 5, aborting:同步命令里的 panic 要穿过 WebKit 的栈帧展开,找不到接住的地方,进程直接退出。
- 同步命令里等窗口属性,应用卡死:窗口 getter 要等主线程回话,同步命令又占着主线程。
- 插件里注册或移除插件,应用卡死:插件钩子和同步插件命令都在插件表的锁里执行,再锁一次就死锁。
- Cannot start a runtime from within a runtime:async 命令里
block_on让 tokio panic,Promise 永远不落定;改成.await。 - prevent_exit 没拦住退出:回调返回后运行时只查一次,先异步问用户再拦已经晚了;先同步拦下,问完再退。
- 命令执行了两次:fetch 失败后同一条消息经 postMessage 重发;响应声明错了类型、页面刷新都会触发,不能重复的命令带幂等键。
- 用事件传大数据很慢:emit 把数据拼进一段 eval,10 MiB 结构化数据让页面停住 2.4 秒;走 Channel 约 50 毫秒。
- Command greet not allowed by ACL:release 只有这一句;debug 分得清新窗口不在能力里、命令名拼错、插件没授权、配置里列了能力导致新文件被忽略。
- 远程页面调不到命令:导航到 http(s) 页面后来源变成远程;
remote.urls经ipc://只匹配不带路径的Origin,远程能力默认还顺带放行本地。 - 写给一个窗口的 deny 对所有窗口生效:拒绝只按来源匹配,不看窗口标签;收窄允许的一侧。
- 配了 CSP,IPC 悄悄退回 postMessage:
connect-src没放行ipc:时只打一条警告就永久换路,原始字节参数变成 JSON。 - 'unsafe-inline' 写了也没用:tauri 补进哈希和 nonce 后
'unsafe-inline'失效,onclick和style属性被拦。 - convertFileSrc 的图片加载失败:feature 没开、CSP 没放行、不在作用域里三种原因,在
<img>上看起来都一样,用fetch区分。 - 窗口关不掉:用了
onCloseRequested就要allow-destroy;页面导航后旧监听器还登记着,窗口一直被拦。 - window.TAURI is undefined:
app.withGlobalTauri默认关闭,写在 1.x 的位置会构建失败,开了也只进主 frame。 - 监听器注册之前发的事件丢了:emit 没有队列也不重放,
setup和on_page_load里发的都早于页面的listen;让页面登记完再通知 Rust。
按出在哪里分:
| 出在哪里 | 坑 |
|---|---|
构建与配置:tauri-build、generate_context! | 1 开发模式崩溃、2 feature 不一致、3 图标、4 反复重编、5 配置文件名 |
| 命令:参数、状态、返回值 | 6 缺键、7 async 借用、8 状态、9 重复标签 |
| 线程:主线程、tokio、锁 | 10 同步命令、11 panic、12 getter 死锁、13 插件锁、14 block_on |
| 生命周期与事件 | 15 prevent_exit、17 大事件、24 关不掉的窗口、26 早发的事件 |
| IPC 通道:fetch 与 postMessage | 16 执行两次、21 CSP 退路 |
| ACL 与能力 | 18 not allowed、19 远程页面、20 deny |
| 前端:CSP、asset 协议、全局 API | 22 'unsafe-inline'、23 asset 图片、25 __TAURI__ |
flowchart TB
q{"碰到了什么"}
q -->|编译或构建失败| bf{"哪一句"}
bf -->|"allowlist"| p2["2 feature 不一致"]
bf -->|"failed to open icon"| p3["3 图标"]
bf -->|"must return a Result"| p7["7 async 借用"]
bf -->|"构建很慢或配置没生效"| p45["4 或 5"]
q -->|进程退出| ex{"怎么退的"}
ex -->|"bus error 无输出"| p1["1 开发模式"]
ex -->|"error 5 aborting"| p11["11 panic"]
ex -->|"拦不住退出"| p15["15 prevent_exit"]
q -->|调用失败| cf{"错误原文"}
cf -->|"missing required key"| p6["6 缺键"]
cf -->|"state not managed"| p8["8 状态"]
cf -->|"not allowed by ACL"| acl["18 或 19 或 20"]
cf -->|"Promise 一直不返回"| p14["14 block_on"]
q -->|卡住或变慢| hang{"哪种"}
hang -->|"别的请求都在等"| p10["10 同步命令"]
hang -->|"永远卡住"| p1213["12 或 13"]
hang -->|"收事件时页面停住"| p17["17 大事件"]
q -->|"没报错但行为不对"| odd{"哪种"}
odd -->|"执行了两次"| p16["16 执行两次"]
odd -->|"事件没收到"| p26["26 早发的事件"]
odd -->|"窗口关不掉"| p24["24 关窗"]
odd -->|"内联脚本或图片不工作"| fe["21 或 22 或 23"]
💬 关联讨论
发起讨论加载中...