{"record":{"id":"914269acf6c8b9e0","repo":"slint-ui/slint","slug":"preview-session-is-no-longer-available","errorCode":null,"errorMessage":"Preview session is no longer available","messagePattern":"Preview session is no longer available","errorType":"exception","errorClass":"std::io::Error","httpStatus":null,"severity":"warning","filePath":"internal/live-preview/preview_sessions.rs","lineNumber":293,"sourceCode":"            })\n        {\n            self.file_cache.borrow_mut().remove(&url);\n            return Err(std::io::Error::other(error.to_string()));\n        }\n        receiver.await.map_err(std::io::Error::other)?\n    }\n\n    fn create_compiler(self: &Rc<Self>) -> slint_interpreter::Compiler {\n        let mut compiler = slint_interpreter::Compiler::new();\n\n        let file_loader_session = Rc::downgrade(self);\n        compiler.set_file_loader(move |path: &std::path::Path| {\n            let url = Url::from_file_path(path);\n            let path_display = path.display().to_string();\n            let session = file_loader_session.clone();\n            Box::pin(async move {\n                let Some(session) = session.upgrade() else {\n                    return Some(Err(std::io::Error::new(\n                        std::io::ErrorKind::BrokenPipe,\n                        \"Preview session is no longer available\",\n                    )));\n                };\n                let Ok(url) = url else {\n                    return Some(Err(std::io::Error::new(\n                        std::io::ErrorKind::InvalidInput,\n                        format!(\"Not an absolute file path: {path_display}\"),\n                    )));\n                };\n                Some(session.request_file(url).await.map(|file_content| {\n                    String::from_utf8_lossy(&file_content.contents).to_string()\n                }))\n            })\n        });\n\n        let mapper_session = Rc::downgrade(self);\n        compiler.compiler_configuration(InternalToken).resource_url_mapper =","sourceCodeStart":275,"sourceCodeEnd":311,"githubUrl":"https://github.com/slint-ui/slint/blob/bb937076de3f7919766c1f25e2e969367cf77e9a/internal/live-preview/preview_sessions.rs#L275-L311","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nlet contents = compile_file(&path).await?; // BrokenPipe aborts everything\n// after\nlet contents = match compile_file(&path).await {\n    Ok(c) => c,\n    Err(e) if e.kind() == std::io::ErrorKind::BrokenPipe => return Ok(()), // session gone\n    Err(e) => return Err(e.into()),\n};","handlingStrategy":"try-catch","validationCode":"// before issuing loads, confirm the session is still alive\nif file_loader_session.upgrade().is_none() { return; }","typeGuard":"fn session_alive(w: &Weak<Session>) -> bool { w.upgrade().is_some() }","tryCatchPattern":"match load(path).await {\n    Err(e) if e.kind() == ErrorKind::BrokenPipe => /* session closed; ignore */,\n    Err(e) => return Err(e.into()),\n    Ok(c) => /* use c */,\n}","preventionTips":["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."],"tags":["live-preview","async","lifecycle","race-condition"],"backgroundTag":"broken-pipe","analyzedSha":"bb937076de3f7919766c1f25e2e969367cf77e9a","analyzedAt":"2026-09-16T01:37:20.251Z","contentChangedAt":"2026-09-16T01:37:20.251Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}