Kuberwastaken/claurst · error
stdin was requested as piped
Error message
stdin was requested as piped
What it means
This panic asserts that `git apply`'s stdin handle is available after spawning the child with `.stdin(Stdio::piped())`. Because piped stdin was explicitly requested, `child.stdin` is guaranteed to be `Some`, so the expect documents an invariant rather than handling a real failure. It can only fire if the spawn configuration was changed to not pipe stdin.
Solutions
- Confirm the git Command still sets `.stdin(Stdio::piped())` before `.spawn()` — that is the invariant this expect guards.
- If stdin configuration became dynamic, replace the expect with `ok_or`/`map_err` returning `MoveError::Apply("stdin not piped".into())`.
- Keep the pipe setup and the `stdin.take()` adjacent so future edits cannot silently decouple them.
- Add a unit test that runs apply_changes against a temp git repo so a removed pipe fails the test instead of panicking in production.
Example fix
// before
let mut stdin = child.stdin.take().expect("stdin was requested as piped");
// after
let mut stdin = child
.stdin
.take()
.ok_or_else(|| MoveError::Apply("git apply stdin was not piped".into()))?; Defensive patterns
Strategy: validation
Validate before calling
// Assert the spawn configuration before relying on stdin:
let mut cmd = std::process::Command::new("git");
cmd.args(["apply", "--whitespace=fix"])
.stdin(std::process::Stdio::piped())
.stdout(std::process::Stdio::piped())
.stderr(std::process::Stdio::piped());
debug_assert!(true, "stdin must remain piped for git apply"); Try / catch
// Panic, not Result — wrap apply_changes:
let res = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| apply_changes(&repo, &patch)));
if res.is_err() { /* report MoveError::Apply("internal: stdin not piped") */ } Prevention
- Keep `.stdin(Stdio::piped())` on the same Command builder as the spawn, never split across helper calls
- Add a regression test running apply_changes against a temp git repo
- Prefer ok_or + error propagation over expect for child handle extraction
- Review any Command-builder refactors for changed stdio settings
When it happens
Trigger: Calling `apply_changes` (via `move_session_changes`) when the preceding `Command::new("git").arg("apply")...spawn()` was configured without `.stdin(Stdio::piped())`, making `child.stdin.take()` return None.
Common situations: A refactor of the git Command builder that removed or conditionally skipped `.stdin(Stdio::piped())`; someone switching stdin to `null()` or `inherit()`; copy-pasting the spawn block into another function without the pipe.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- Failed to start LSP server
- generationConfig must be an object
- Invalid : contains unsafe characters
- Login succeeded but could not obtain a usable credential
- Stdin closed unexpectedly
AI-assisted analysis of Kuberwastaken/claurst@b0637c97ec (2026-09-10).
Data as JSON: /api/errors/11e188caaefbe694.
Report an issue: GitHub.
Appendix: source
Thrown at src-rust/crates/commands/src/new_move.rs:339
}
/// Apply a captured patch to the destination worktree via `git apply -`.
fn apply_changes(dest_root: &Path, patch: &str) -> Result<(), MoveError> {
use std::io::Write;
use std::process::Stdio;
let mut child = Command::new("git")
.current_dir(dest_root)
.args(["apply", "-"])
.stdin(Stdio::piped())
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.spawn()
.map_err(|e| MoveError::Apply(e.to_string()))?;
// Stream the patch on a separate thread so a large patch can't deadlock
// against git filling its stdout/stderr pipes.
let mut stdin = child.stdin.take().expect("stdin was requested as piped");
let patch_owned = patch.to_string();
let writer = std::thread::spawn(move || {
let _ = stdin.write_all(patch_owned.as_bytes());
// `stdin` drops here, closing the pipe so git sees EOF.
});
let output = child
.wait_with_output()
.map_err(|e| MoveError::Apply(e.to_string()))?;
let _ = writer.join();
if output.status.success() {
Ok(())
} else {
Err(MoveError::Apply(git_stderr(&output, "git apply failed")))
}
}
View on GitHub (pinned to b0637c97ec)