GitoxideLabs/gitoxide · error
configured beforehand
Error message
configured beforehand
What it means
Panic from `child.stderr.take().expect("configured beforehand")` in the blocking file transport's `handshake`. When SSH is used, the code asserts the spawned child has a piped stderr, which requires `Command::stderr(Stdio::piped())` to have been called before `spawn()`. The panic fires only if the spawn setup forgot to configure stderr — an internal setup invariant, not user input.
Solutions
- Ensure the code path that spawns the SSH child calls `.stderr(Stdio::piped())` (and stdout/stdin) before `spawn()`.
- Upgrade gix-transport to a version where SSH spawn configures all pipes.
- If using a custom `GIT_SSH_COMMAND` wrapper, verify the failure isn't from a locally modified transport build.
Example fix
// before let child = cmd.spawn()?; // stderr not piped // after let child = cmd.stderr(Stdio::piped()).stdout(Stdio::piped()).stdin(Stdio::piped()).spawn()?;
Defensive patterns
Strategy: try-catch
Try / catch
std::panic::catch_unwind(AssertUnwindSafe(|| handshake(...)))
.map_err(|_| anyhow::anyhow!("SSH handshake panicked: stderr pipe not configured"))? Prevention
- Always pipe stdout/stderr/stdin via Stdio::piped() before spawn in any custom transport code
- Avoid modifying the SSH spawn path in forks without testing SSH remotes
- Test against an SSH remote in CI when touching transport code
When it happens
Trigger: Performing a handshake over an SSH remote (ssh_kind present) when the child process was spawned without `Stdio::piped()` for stderr, e.g. in a patched build or after changes to the spawn code path.
Common situations: Custom ssh_cmd wrappers or forks that alter process spawning; regressions in gix-transport after refactoring the SSH invocation.
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
- configured
- only value and unspecified are possible here
- parent-match assures this
- upper match already assured we only deal with blobs
- fixed size array with three items
AI-assisted analysis of GitoxideLabs/gitoxide@e73179060b (2026-09-08).
Data as JSON: /api/errors/78acfe562d3167b8.
Report an issue: GitHub.
Appendix: source
Thrown at gix-transport/src/client/blocking_io/file.rs:311
let (cmd, cmd_name) = self.prepare_fallback_command(service);
let mut cmd = into_std_command(cmd);
gix_features::trace::debug!(command = ?cmd, "gix_transport::SpawnProcessOnDemand (fallback)");
cmd.spawn().map_err(|err| client::Error::InvokeProgram {
source: err,
command: cmd_name,
})?
}
Err(err) => {
return Err(client::Error::InvokeProgram {
source: err,
command: cmd_name,
});
}
};
let stdout: Box<dyn std::io::Read + Send> = match ssh_kind {
Some(ssh_kind) => Box::new(supervise_stderr(
ssh_kind,
child.stderr.take().expect("configured beforehand"),
child.stdout.take().expect("configured"),
)),
None => Box::new(child.stdout.take().expect("stdout configured")),
};
self.connection = Some(Connection::new_for_spawned_process(
stdout,
child.stdin.take().expect("stdin configured"),
self.desired_version,
self.path.clone(),
self.trace,
));
self.child = Some(child);
self.connection
.as_mut()
.expect("connection to be there right after setting it")
.handshake(service, extra_parameters)
}
View on GitHub (pinned to e73179060b)