{"record":{"id":"168ede8e602601b3","repo":"GraphiteEditor/Graphite","slug":"failed-to-connect-to-the-main-process-bootstrap-se","errorCode":null,"errorMessage":"Failed to connect to the main process bootstrap server","messagePattern":"Failed to connect to the main process bootstrap server","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"desktop/ui/src/remote/host.rs","lineNumber":29,"sourceCode":"use crate::frames::sequence::SequenceState;\n#[cfg(target_os = \"macos\")]\nuse crate::platform::mac;\n\npub(crate) fn run() {\n\t// Ignore SIGINT, the controlling process is responsible for shutting down the host\n\t#[cfg(any(target_os = \"linux\", target_os = \"macos\"))]\n\tunsafe {\n\t\tlibc::signal(libc::SIGINT, libc::SIG_IGN);\n\t}\n\n\tlet args: Vec<String> = std::env::args().collect();\n\tlet config = HostConfig::from_args(&args).expect(\"CEF host started without a valid host config argument\");\n\tlet acceleration_requested = config.acceleration;\n\n\t#[cfg(target_os = \"macos\")]\n\tmac::spawn_parent_watchdog(config.main_pid);\n\n\tlet bootstrap = IpcSender::<EventMessage>::connect(config.server.clone()).expect(\"Failed to connect to the main process bootstrap server\");\n\tlet event_sender = Arc::new(Mutex::new(bootstrap));\n\tlet (control_sender, control_receiver) = ipc_channel::ipc::channel::<HostControlMessage>().expect(\"Failed to create control channel\");\n\n\t#[cfg(feature = \"accelerated_paint\")]\n\tlet plane = if acceleration_requested { PlaneSender::from_config(&config, event_sender.clone()) } else { None };\n\t#[cfg(feature = \"accelerated_paint\")]\n\tlet acceleration = plane.is_some();\n\t#[cfg(not(feature = \"accelerated_paint\"))]\n\tlet acceleration = {\n\t\tif acceleration_requested {\n\t\t\ttracing::error!(\"UI acceleration requested but the accelerated_paint feature is disabled; using software frames\");\n\t\t}\n\t\tfalse\n\t};\n\n\tevent_sender\n\t\t.lock()\n\t\t.expect(\"The host message sender cannot be poisoned before threads exist\")","sourceCodeStart":11,"sourceCodeEnd":47,"githubUrl":"https://github.com/GraphiteEditor/Graphite/blob/c507b356453361e31638b8bff8f6d46b6da2961e/desktop/ui/src/remote/host.rs#L11-L47","documentation":"Panic in the out-of-process CEF UI host when IpcSender::<EventMessage>::connect fails to connect to the bootstrap IPC server created by the main Graphite process (the address arrives via the HostConfig 'server' argument). ipc-channel connects over a Unix domain socket (Linux/macOS) or named pipe (Windows); connect fails when nothing is listening, the path is stale or wrong, or the sandbox denies connecting.","triggerScenarios":"The main process died or exited between spawning the host process and the host's connect call; a stale socket path passed through the host config; running the host under a sandbox/container that blocks the socket namespace; permission mismatch between the two processes' users.","commonSituations":"The parent Graphite process crashing at startup right after spawning the UI host; kill -9 of the main process leaving the host to fail connecting; security software blocking local sockets; mismatched builds where the config serialization changed.","solutions":["Check whether the main Graphite process (whose pid is passed in the config) is still alive at the moment of failure","Look for a crash log/stack trace of the main process, since its early death is the usual root cause","Verify both processes run as the same user and no sandbox blocks the local socket","Re-launch the app; if it reproduces, run with logging to capture the main process's startup error"],"exampleFix":"// before\nlet bootstrap = IpcSender::<EventMessage>::connect(config.server.clone()).expect(\"Failed to connect to the main process bootstrap server\");\n\n// after\nlet bootstrap = IpcSender::<EventMessage>::connect(config.server.clone()).unwrap_or_else(|e| {\n\teprintln!(\"Failed to connect to the main process bootstrap server at {:?}: {e} (is the main process {} still running?)\", config.server, config.main_pid);\n\tstd::process::exit(1);\n});","handlingStrategy":"retry","validationCode":"// Before connecting, check the main process is still alive (pid comes from the host config)\nfn main_process_alive(pid: u32) -> bool {\n\t!std::path::PathBuf::from(format!(\"/proc/{pid}\")).exists() || std::path::Path::new(&format!(\"/proc/{pid}\")).exists()\n}","typeGuard":null,"tryCatchPattern":"let mut last_err = None;\nfor _ in 0..5 {\n\tmatch IpcSender::<EventMessage>::connect(config.server.clone()) {\n\t\tOk(sender) => return sender,\n\t\tErr(e) => {\n\t\t\tlast_err = Some(e);\n\t\t\tstd::thread::sleep(Duration::from_millis(100)); // main process may still be binding\n\t\t}\n\t}\n}\npanic!(\"Failed to connect to the main process bootstrap server after retries: {:?}\", last_err);","preventionTips":["Verify the main process pid (passed via HostConfig) is alive before/while connecting","Add a short bounded retry to absorb startup races between the main process binding and the host connecting","Log the server address in the failure so stale-config issues are visible"],"tags":["rust","ipc","ipc-channel","cef","multi-process","connection-refused"],"backgroundTag":"ipc-connection-refused","analyzedSha":"c507b356453361e31638b8bff8f6d46b6da2961e","analyzedAt":"2026-08-16T21:57:18.596Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}