GraphiteEditor/Graphite · error
Failed to connect to the main process bootstrap server
Error message
Failed to connect to the main process bootstrap server
What it means
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.
Source
Thrown at desktop/ui/src/remote/host.rs:29
use crate::frames::sequence::SequenceState;
#[cfg(target_os = "macos")]
use crate::platform::mac;
pub(crate) fn run() {
// Ignore SIGINT, the controlling process is responsible for shutting down the host
#[cfg(any(target_os = "linux", target_os = "macos"))]
unsafe {
libc::signal(libc::SIGINT, libc::SIG_IGN);
}
let args: Vec<String> = std::env::args().collect();
let config = HostConfig::from_args(&args).expect("CEF host started without a valid host config argument");
let acceleration_requested = config.acceleration;
#[cfg(target_os = "macos")]
mac::spawn_parent_watchdog(config.main_pid);
let bootstrap = IpcSender::<EventMessage>::connect(config.server.clone()).expect("Failed to connect to the main process bootstrap server");
let event_sender = Arc::new(Mutex::new(bootstrap));
let (control_sender, control_receiver) = ipc_channel::ipc::channel::<HostControlMessage>().expect("Failed to create control channel");
#[cfg(feature = "accelerated_paint")]
let plane = if acceleration_requested { PlaneSender::from_config(&config, event_sender.clone()) } else { None };
#[cfg(feature = "accelerated_paint")]
let acceleration = plane.is_some();
#[cfg(not(feature = "accelerated_paint"))]
let acceleration = {
if acceleration_requested {
tracing::error!("UI acceleration requested but the accelerated_paint feature is disabled; using software frames");
}
false
};
event_sender
.lock()
.expect("The host message sender cannot be poisoned before threads exist")View on GitHub (pinned to c507b35645)
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
Example fix
// before
let bootstrap = IpcSender::<EventMessage>::connect(config.server.clone()).expect("Failed to connect to the main process bootstrap server");
// after
let bootstrap = IpcSender::<EventMessage>::connect(config.server.clone()).unwrap_or_else(|e| {
eprintln!("Failed to connect to the main process bootstrap server at {:?}: {e} (is the main process {} still running?)", config.server, config.main_pid);
std::process::exit(1);
}); Defensive patterns
Strategy: retry
Validate before calling
// Before connecting, check the main process is still alive (pid comes from the host config)
fn main_process_alive(pid: u32) -> bool {
!std::path::PathBuf::from(format!("/proc/{pid}")).exists() || std::path::Path::new(&format!("/proc/{pid}")).exists()
} Try / catch
let mut last_err = None;
for _ in 0..5 {
match IpcSender::<EventMessage>::connect(config.server.clone()) {
Ok(sender) => return sender,
Err(e) => {
last_err = Some(e);
std::thread::sleep(Duration::from_millis(100)); // main process may still be binding
}
}
}
panic!("Failed to connect to the main process bootstrap server after retries: {:?}", last_err); Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Failed to send Hello to the main process
- Failed to create control channel
- Failed to spawn socket thread
- Failed to spawn the CEF control thread
- The CEF control thread ended without a result
AI-assisted analysis of GraphiteEditor/Graphite@c507b35645 (2026-08-16).
Data as JSON: /api/errors/168ede8e602601b3.
Report an issue: GitHub.