GitoxideLabs/gitoxide · error
named threads with small stack work on all platforms
Error message
named threads with small stack work on all platforms
What it means
Panic from `std::thread::Builder::spawn().expect("named threads with small stack work on all platforms")` inside `supervise_stderr`, which launches a helper thread to forward a child process's stderr during a transport handshake. The expect asserts that spawning a small-stack named thread always succeeds; failure means the OS refused to create the thread (resource exhaustion or platform limitation).
Solutions
- Raise the thread/process limit (`ulimit -u`) or container PID limit and retry.
- Free resources (reduce concurrent connections) before retrying the fetch/push.
- If on an exotic platform, run the blocking transport on a default-size stack, or use the async transport instead.
- Retry the operation once resources are available — it is transient.
Defensive patterns
Strategy: retry
Validate before calling
if rlimit::getrlimit(rlimit::Resource::NPROC).map(|(_, hard)| hard == 0).unwrap_or(false) {
anyhow::bail!("thread/process limit too low for transport threads");
} Try / catch
match std::panic::catch_unwind(AssertUnwindSafe(|| transport.handshake(version))) {
Ok(r) => r?,
Err(_) => { wait_for_resources(); anyhow::bail!("handshake thread spawn failed; retry after raising limits"); }
} Prevention
- Raise RLIMIT_NPROC / container PID limits in constrained environments
- Limit concurrent fetch/push operations
- On exotic targets, test thread spawning with small stacks early
- Fall back to the async transport where thread spawning differs
When it happens
Trigger: Calling a blocking transport `handshake` (spawning `git upload-pack`/`receive-pack` or an SSH command) when thread creation fails — e.g. hitting RLIMIT_NPROC/`ulimit -u`, out of memory, or a platform where the small stack size is rejected.
Common situations: Containers with very low thread/process limits, deeply recursive workloads exhausting threads, or unusual/embedded targets with restrictive pthread settings.
Related errors
- configured beforehand
- configured
- ' ' is not a valid configuration key
- Cannot use iter_v1() on index of type
- Cannot use iter_v2() on index of type
AI-assisted analysis of GitoxideLabs/gitoxide@e73179060b (2026-09-08).
Data as JSON: /api/errors/f8db95d50935131d.
Report an issue: GitHub.
Appendix: source
Thrown at gix-transport/src/client/blocking_io/file.rs:262
.name("supervise ssh stderr".into())
.stack_size(128 * 1024)
.spawn(move || -> std::io::Result<()> {
let mut process_stderr = std::io::stderr();
for line in std::io::BufReader::new(stderr).byte_lines() {
let line = line?;
match ssh_kind.line_to_err(line.into()) {
Ok(err) => {
send.send(err).ok();
}
Err(line) => {
process_stderr.write_all(&line).ok();
writeln!(&process_stderr).ok();
}
}
}
Ok(())
})
.expect("named threads with small stack work on all platforms");
ReadStdoutFailOnError { read: stdout, recv }
}
impl client::blocking_io::Transport for SpawnProcessOnDemand {
fn handshake<'a>(
&mut self,
service: Service,
extra_parameters: &'a [(&'a str, Option<&'a str>)],
) -> Result<SetServiceResponse<'_>, client::Error> {
let (cmd, ssh_kind, cmd_name) = self.prepare_command(service)?;
let envs = std::mem::take(&mut self.envs);
let into_std_command = |mut cmd: gix_command::Prepare| {
cmd.stdin = Stdio::piped();
cmd.stdout = Stdio::piped();
let mut cmd = std::process::Command::from(cmd);
for env_to_remove in ENV_VARS_TO_REMOVE {
cmd.env_remove(env_to_remove);View on GitHub (pinned to e73179060b)