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

  1. Discard the failed compile result — the session that requested it no longer exists; start a compile on the new session instead.
  2. Ensure the session (Arc) is kept alive for the duration of in-flight compiler operations, or cancel pending work before dropping it.
  3. 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

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


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)