slint-ui/slint · warning · std::io::Error
Preview session is no longer available
Error message
Preview session is no longer available
What it means
The live-preview compiler installs a file loader that holds a Weak reference to the current file_loader_session. If the session has been dropped (preview closed or restarted) by the time the loader's async body runs, the upgrade fails and the loader returns a BrokenPipe io::Error with this message instead of file contents.
Solutions
- Discard the failed compile result — the session that requested it no longer exists; start a compile on the new session instead.
- Ensure the session (Arc) is kept alive for the duration of in-flight compiler operations, or cancel pending work before dropping it.
- Treat BrokenPipe from the loader as a benign shutdown signal rather than a hard failure.
Example fix
// before
let contents = compile_file(&path).await?; // BrokenPipe aborts everything
// after
let contents = match compile_file(&path).await {
Ok(c) => c,
Err(e) if e.kind() == std::io::ErrorKind::BrokenPipe => return Ok(()), // session gone
Err(e) => return Err(e.into()),
}; Defensive patterns
Strategy: try-catch
Validate before calling
// before issuing loads, confirm the session is still alive
if file_loader_session.upgrade().is_none() { return; } Type guard
fn session_alive(w: &Weak<Session>) -> bool { w.upgrade().is_some() } Try / catch
match load(path).await {
Err(e) if e.kind() == ErrorKind::BrokenPipe => /* session closed; ignore */,
Err(e) => return Err(e.into()),
Ok(c) => /* use c */,
} Prevention
- Keep an owned Arc clone of the session alive until all in-flight compiler futures complete.
- Treat BrokenPipe from the live-preview loader as an expected shutdown signal and swallow it.
- Cancel outstanding loads when closing a session instead of letting them race with teardown.
When it happens
Trigger: set_file_loader closure invoked after the preview session that created it was torn down; any async file load racing with session shutdown — session.upgrade() returns None.
Common situations: Closing the preview window or restarting a session while a compile is in flight; outstanding async loads from the old compiler instance resolving after the new session replaced the old one.
Related errors
- File not found
- Callback ' ' cannot be used with a callback decorator for…
- Callback ' ' cannot be used with a callback decorator for…
- Callback ' ' in global ' ' cannot be used with a callback…
- Cannot get property
AI-assisted analysis of slint-ui/slint@bb937076de (2026-09-16).
Data as JSON: /api/errors/914269acf6c8b9e0.
Report an issue: GitHub.
Appendix: source
Thrown at internal/live-preview/preview_sessions.rs:293
})
{
self.file_cache.borrow_mut().remove(&url);
return Err(std::io::Error::other(error.to_string()));
}
receiver.await.map_err(std::io::Error::other)?
}
fn create_compiler(self: &Rc<Self>) -> slint_interpreter::Compiler {
let mut compiler = slint_interpreter::Compiler::new();
let file_loader_session = Rc::downgrade(self);
compiler.set_file_loader(move |path: &std::path::Path| {
let url = Url::from_file_path(path);
let path_display = path.display().to_string();
let session = file_loader_session.clone();
Box::pin(async move {
let Some(session) = session.upgrade() else {
return Some(Err(std::io::Error::new(
std::io::ErrorKind::BrokenPipe,
"Preview session is no longer available",
)));
};
let Ok(url) = url else {
return Some(Err(std::io::Error::new(
std::io::ErrorKind::InvalidInput,
format!("Not an absolute file path: {path_display}"),
)));
};
Some(session.request_file(url).await.map(|file_content| {
String::from_utf8_lossy(&file_content.contents).to_string()
}))
})
});
let mapper_session = Rc::downgrade(self);
compiler.compiler_configuration(InternalToken).resource_url_mapper =View on GitHub (pinned to bb937076de)