slint-ui/slint · critical
Could not find executable name of the slint-lsp
Error message
Could not find executable name of the slint-lsp
What it means
When the preview-engine feature spawns an embedded live preview as a child process, slint-lsp resolves its own binary path with `std::env::current_exe().expect(...)` to re-invoke itself as `slint-lsp live-preview --remote-controlled`. `current_exe` fails when the OS cannot determine the path of the running executable, and the expect then panics, aborting `main_loop` startup.
Solutions
- Ensure /proc is mounted in the container (e.g. mount -t proc proc /proc) so /proc/self/exe is resolvable.
- Verify the slint-lsp binary on disk has not been deleted or replaced (deleted-file inode) while the LSP is running; restart from a valid path.
- Build/run slint-lsp with the preview-engine child-process requirement avoided: use the embedded preview path or a slint-lsp build/feature configuration that does not spawn `live-preview`.
- As a code-level fix, replace the expect with a graceful fallback (e.g. locate the binary via PATH or skip the child-process preview) and log an error instead of panicking.
Example fix
// before
let exe = std::env::current_exe().expect("Could not find executable name of the slint-lsp");
// after
let exe = std::env::current_exe().unwrap_or_else(|e| {
tracing::error!("cannot resolve own executable ({e}); disabling child preview");
std::process::exit(1);
}); Defensive patterns
Strategy: validation
Validate before calling
// deployment check before enabling the child-process preview
if !std::path::Path::new("/proc/self/exe").exists() {
eprintln("/proc unavailable: embedded child preview will fail to spawn");
} Type guard
fn current_exe_ok() -> bool { std::env::current_exe().is_ok() } Try / catch
// at startup, resolve once and fail fast with a clear message
let exe = std::env::current_exe()
.map_err(|e| format!("cannot locate slint-lsp binary for child preview: {e}"))?; Prevention
- Mount /proc in containers that run slint-lsp with the preview engine.
- Do not delete or atomically replace the LSP binary while it is running.
- Avoid exec'ing slint-lsp from memory-only mechanisms (memfd) in preview mode.
- Prefer the embedded (non-child-process) preview when running in restricted sandboxes.
When it happens
Trigger: Running slint-lsp in an environment where /proc is unavailable or the binary path is unreadable: deleted binary after exec (Linux), containers/chroots without /proc mounted, some FreeBSD/NetBSD configurations, binaries run from memfd or via unusual exec mechanisms, or restricted permission setups.
Common situations: Docker images that unmount /proc or run with restricted procfs; security sandboxes hiding /proc/self/exe; running the LSP binary from a tmpfs that was cleaned while running; embedding slint-lsp inside a single-binary packer that execs from memory.
Understand the failure class
Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.
Related errors
- Child has no stdin
- Child has no stdout
- Callbacks were set up earlier
- EditorSession must have at least one preview
- Failed to join adapter thread
AI-assisted analysis of slint-ui/slint@bb937076de (2026-09-16).
Data as JSON: /api/errors/1b07a3d9f4460c8f.
Report an issue: GitHub.
Appendix: source
Thrown at tools/lsp/main.rs:312
) -> Result<()> {
let request_queue = OutgoingRequestQueue::default();
#[cfg_attr(not(feature = "preview-engine"), allow(unused))]
let (preview_to_lsp_sender, preview_to_lsp_receiver) =
mpsc::unbounded_channel::<PreviewToLspMessage>();
let server_notifier = ServerNotifier::new(connection.sender.clone(), request_queue.clone());
#[cfg(not(feature = "preview-engine"))]
let to_preview = LspToPreviews::with_one(editor_preview::DummyLspToPreview::default());
#[cfg(feature = "preview-engine")]
let to_preview = {
use i_slint_live_preview::protocol::PreviewTarget;
let sn = server_notifier.clone();
let child_preview: Box<dyn editor_preview::LspToPreview> =
Box::new(connector::ChildProcessLspToPreview::new(
std::env::current_exe().expect("Could not find executable name of the slint-lsp"),
vec!["live-preview".into(), "--remote-controlled".into()],
preview_to_lsp_sender.clone(),
));
let embedded_preview: Box<dyn editor_preview::LspToPreview> =
Box::new(connector::EmbeddedLspToPreview::new(sn.clone()));
LspToPreviews::new(
std::collections::HashMap::from([
(PreviewTarget::ChildProcess, child_preview),
(PreviewTarget::EmbeddedWasm, embedded_preview),
]),
PreviewTarget::ChildProcess,
#[cfg(feature = "preview-remote")]
|to_previews| {
Rc::new(connector::remote::RemoteLspToPreview::new(
preview_to_lsp_sender.clone(),
to_previews,
))
},View on GitHub (pinned to bb937076de)