{"record":{"id":"0d2acb72ddf474f6","repo":"slint-ui/slint","slug":"child-has-no-stdin","errorCode":null,"errorMessage":"Child has no stdin","messagePattern":"Child has no stdin","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/editor-preview/child_process.rs","lineNumber":55,"sourceCode":"    fn preview_is_running(&self) -> bool {\n        self.inner.borrow().as_ref().map(|i| !i.communication_handle.is_finished()).unwrap_or(false)\n    }\n\n    fn start_preview(&self) -> crate::Result<()> {\n        if let Some(inner) = self.inner.borrow_mut().take() {\n            inner.communication_handle.abort();\n        }\n\n        let mut child = tokio::process::Command::new(&self.executable)\n            .args(&self.arguments)\n            .stdin(std::process::Stdio::piped())\n            .stdout(std::process::Stdio::piped())\n            .spawn()?;\n\n        tracing::debug!(\"Preview process spawned (PID {:?})\", child.id());\n\n        let from_child = child.stdout.take().expect(\"Child has no stdout\");\n        let mut to_child = child.stdin.take().expect(\"Child has no stdin\");\n\n        let channel = self.preview_to_lsp_channel.clone();\n\n        let communication_handle = tokio::spawn(async move {\n            let _exited_guard = scopeguard::guard(channel.clone(), |channel| {\n                channel.send(PreviewToLspMessage::Exited).ok();\n            });\n            let reader = tokio::io::BufReader::new(from_child);\n            let mut lines = reader.lines();\n            while let Some(line) = lines.next_line().await.map_err(|e| e.to_string())? {\n                if let Ok(message) = serde_json::from_str(&line) {\n                    channel.send(message).map_err(|e| e.to_string())?;\n                }\n            }\n\n            let exit_status = child.wait().await.map_err(|e| e.to_string());\n\n            if exit_status.map(|exit_status| !exit_status.success()).unwrap_or(true) {","sourceCodeStart":37,"sourceCodeEnd":73,"githubUrl":"https://github.com/slint-ui/slint/blob/bb937076de3f7919766c1f25e2e969367cf77e9a/internal/editor-preview/child_process.rs#L37-L73","documentation":"Same family as [212] but for stdin: the preview child is spawned with `stdin(Stdio::piped())` and `child.stdin.take()` must yield the pipe. None means the pipe was not configured or already taken. This is an internal invariant; stock builds always pipe stdin.","triggerScenarios":"`start_preview` (called from `send`) after the child's stdin handle was already taken, or if the spawn's `.stdin(Stdio::piped())` was dropped/modified.","commonSituations":"Patched builds changing spawn options; calling start_preview twice on the same Child struct; a bug in preview restart logic reusing handles.","solutions":["Ensure `.stdin(std::process::Stdio::piped())` is present in the spawn options","Take stdin only once per spawned child; spawn a fresh child for each preview session","Rebuild slint-lsp from a clean checkout","File a bug if reproducible on an unmodified build"],"exampleFix":"// before: reusing stale child\nlet child = &mut self.cached_child;\nlet mut to_child = child.stdin.take().expect(\"Child has no stdin\");\n\n// after: spawn fresh per session\nlet mut child = command.spawn()?;\nlet mut to_child = child.stdin.take().expect(\"Child has no stdin\");","handlingStrategy":"validation","validationCode":"let Some(stdin) = child.stdin.take() else { return Err(\"preview child stdin missing\"); };","typeGuard":"fn has_stdin(child: &std::process::Child) -> bool { child.stdin.is_some() }","tryCatchPattern":"// treat a missing pipe as a restartable failure\nif child.stdin.is_none() { respawn_preview()?; }","preventionTips":["Keep `.stdin(std::process::Stdio::piped())` in spawn options","Take stdin only once per child","Restart logic should spawn a new process, not reuse an old Child"],"tags":["lsp","process","editor-preview","panic"],"backgroundTag":"internal-invariant-violation","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"}