A JavaScript error occurred in the main process
Uncaught Exception:
Error: Cannot create BrowserWindow before app is ready
at initMainWindow (/Applications/SiYuan.app/Contents/Resources/app/electron/main.js:397:27)
at EventEmitter.<anonymous> (/Applications/SiYuan.app/Contents/Resources/app/electron/main.js:1503:9)
at EventEmitter.emit (node:events:508:28)
## 错误含义
这是 **Electron 生命周期** 问题,不是内核或笔记数据问题。
报错信息:
```text
Error: Cannot create BrowserWindow before app is ready
```
含义:在 Electron 的 `app` 尚未完成初始化(未触发 `ready` / `app.whenReady()` 尚未完成)时,就调用了 `new BrowserWindow()`。Electron 不允许这样做。
堆栈指向 `initMainWindow` 里创建主窗口,以及 `main.js` 约 1503 行的 `activate` 事件监听——与当前源码一致。
## 触发原因(macOS 常见)
正常启动流程在 `app.whenReady()` 里走 `initKernel` → `initMainWindow`:
```736:737:app/electron/main.js
app.whenReady().then(() => {
const resetTrayMenu = (tray, lang, mainWindow) => {
```
但 macOS 还会在 Dock 点击等场景触发 `activate`,且 **可能在 `app` 尚未 ready 时就触发**(Electron 官方也认为这是合法行为)。
当前 `activate` 处理如下:
```1502:1511:app/electron/main.js
app.on("activate", () => {
if (workspaces.length > 0) {
const mainWindow = (latestActiveWindow && !latestActiveWindow.isDestroyed()) ? latestActiveWindow : workspaces[0].browserWindow;
if (mainWindow && !mainWindow.isDestroyed()) {
mainWindow.show();
}
}
if (BrowserWindow.getAllWindows().length === 0) {
initMainWindow();
}
});
```
若启动时 `activate` 早于 `whenReady` 完成,且此时还没有任何窗口(`getAllWindows().length === 0`),就会直接调用 `initMainWindow()`,在约 402 行执行 `new BrowserWindow()` 并崩溃。
典型场景:
- 启动阶段用户很快点击 Dock 图标
- 系统或启动项在应用尚未 ready 时激活应用
- 冷启动较慢时,`activate` 与 `whenReady` 竞态
## 与截图的对应关系
| 项目 | 说明 |
|------|------|
| 平台 | `/Applications/SiYuan.app`,macOS |
| 出错位置 | `initMainWindow` 内 `new BrowserWindow` |
| 调用链 | `app.on("activate")` → `initMainWindow()` |
| 性质 | 主进程未捕获异常,启动即弹窗 |
## 修复思路(供参考)
在 `activate` 里创建窗口前,先判断 `app.isReady()`;或把 `activate` 监听注册放到 `app.whenReady()` 内部(与 [electron-quick-start 的修复](https://github.com/electron/electron-quick-start/pull/382) 类似):
```javascript
app.on("activate", () => {
if (!app.isReady()) {
return;
}
// 原有逻辑...
});
```
这样 `whenReady` 仍会负责首次正常启动;`activate` 只在 ready 之后、且确实没有窗口时再重建窗口,避免竞态崩溃。
---
**总结**:用户反馈的是 **macOS 上 `activate` 过早触发、在 `app` 未 ready 时创建主窗口** 导致的启动崩溃,属于 Electron 主进程代码问题,而非用户配置或数据损坏。
如果你需要,我可以在仓库里直接加上 `app.isReady()` 防护并提一个小 patch。
https://ld246.com/article/1780623219729
AI 分析: