siyuan-note/siyuan · error · Error

failed to terminate residual kernel processes [ports=" + res

Error message

failed to terminate residual kernel processes [ports=" + residualPorts.join(",") + "]

What it means

During the update flow, after waiting for kernel processes on timed-out ports to exit, some ports still have live kernel processes. On Windows the installer handles killing them, but on non-Windows platforms Electron has no reliable way to kill them, so it aborts the update with this error naming the affected ports.

Source

Thrown at app/electron/main.js:1703

    if (timedOutPorts.length === 0) {
        return;
    }

    writeLog("kernel exit timed out before update [ports=" + timedOutPorts.join(",") + "]");
    timedOutPorts.forEach((port) => {
        const kernelProcess = kernelProcesses.get(port);
        if (kernelProcess) {
            writeLog("terminating residual kernel before update [pid=" + kernelProcess.pid + ", port=" + port + "]");
            kernelProcess.kill("SIGKILL");
        }
    });
    await Promise.all(timedOutPorts.map((port) => waitForKernelProcessExit(port, 5000)));
    const residualPorts = timedOutPorts.filter((port) => kernelProcesses.has(port));
    if (residualPorts.length > 0) {
        if (process.platform === "win32") {
            writeLog("residual kernel processes will be terminated by the installer [ports=" + residualPorts.join(",") + "]");
        } else {
            throw new Error("failed to terminate residual kernel processes [ports=" + residualPorts.join(",") + "]");
        }
    }
};

const closeUpdateKernelStage = async (ports, request) => {
    if (ports.length === 0) {
        return [];
    }

    const exitResponses = await Promise.all(ports.map((port) => closeKernelForUpdate(port, request.initiatingPort,
        request.setCurrentWorkspace)));
    ports.forEach((port) => exitApp(port));
    await waitForUpdateKernelExits(ports);
    return exitResponses;
};

// 更新时先退出其他工作空间,再退出发起更新的工作空间,确保安装器启动前所有内核已经停止。
// https://github.com/siyuan-note/siyuan/issues/18258

View on GitHub (pinned to 8641553a1f)

Solutions

  1. Manually inspect and kill the lingering kernel process for the listed ports (lsof -i :PORT / ps aux | grep siyuan-kernel), then retry the update
  2. Close all other SiYuan workspaces before updating so fewer kernels need to exit
  3. Reboot if the process is unkillable (e.g. stuck in uninterruptible I/O sleep)
  4. On Windows, no action is needed: the installer is expected to terminate residual processes

Example fix

// Hard to fix in caller code; operator-level remediation:
// before
//   update fails: failed to terminate residual kernel processes [ports=6806]
// after
//   $ lsof -i :6806          # find PID holding the port
//   $ kill -9 <pid>
//   # retry the in-app update
Defensive patterns

Strategy: validation

Validate before calling

if !notebookCryptoConfigurationComplete(&Conf.NotebookCrypto) {
    // repair via backup import or re-run EnableEncryptedNotebook before saving
}

Prevention

When it happens

Trigger: An in-app update is initiated while kernel processes from this or other workspaces ignore SIGTERM/SIGKILL within the 5-second waitForKernelProcessExit window on Linux/macOS; residualPorts is non-empty and process.platform !== "win32".

Common situations: A frozen or wedged kernel process holding the workspace port; multiple open workspaces whose kernels have not shut down in time; a kernel stuck in startup/shutdown due to I/O or a deadlock; running the app under a process supervisor that respawns kernels.

Related errors


AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11). Data as JSON: /api/errors/3ad1edd0131fe6dd. Report an issue: GitHub.