zed-industries/zed · critical
Remote server exited with status {status}
Error message
Remote server exited with status {status} What it means
Once the remote server is started in the container, Zed multiplexes RPC messages over its stdio; when the child terminates, the status is compared against 0 and any non-zero exit surfaces as this error. The number is zed-remote-server's raw exit status, meaning the server process itself died after launch.
Source
Thrown at crates/remote/src/transport/docker.rs:743
let Ok(child) = command.spawn() else {
return Task::ready(Err(anyhow::anyhow!(
"Failed to start remote server process"
)));
};
let mut proxy_process = self.proxy_process.lock();
*proxy_process = Some(child.id());
cx.spawn(async move |cx| {
super::handle_rpc_messages_over_child_process_stdio(
child,
incoming_tx,
outgoing_rx,
connection_activity_tx,
cx,
)
.await
.and_then(|status| {
if status != 0 {
anyhow::bail!("Remote server exited with status {status}");
}
Ok(0)
})
})
}
fn upload_directory(
&self,
src_path: PathBuf,
dest_path: RemotePathBuf,
cx: &App,
) -> Task<Result<()>> {
let dest_path_str = dest_path.to_string();
let src_path_display = src_path.display().to_string();
let upload_task = Self::upload_and_chown(View on GitHub (pinned to 5a9b9558db)
Solutions
- Run the binary directly in the container to see the loader/runtime error: `docker exec -it <id> <server_path> version` (or `ldd <server_path>`)
- Match architectures: pull the image for the container's real platform (`docker run --platform linux/arm64 ...`) or upload the matching server build
- Use a base image with a recent glibc or musl (debian bookworm, alpine) rather than ancient or empty bases
- Check whether the OOM killer terminated it: `docker inspect <id>` for OOMKilled, and raise the memory limit
Example fix
# before: amd64 image on arm64 host FROM debian:bullseye # after: match container platform to host/server build FROM --platform=linux/arm64 debian:bookworm
Defensive patterns
Strategy: try-catch
Validate before calling
async fn server_binary_runs(conn: &DockerExecConnection, path: &str) -> bool {
conn.run_docker_exec(path, None, &Default::default(), &["version"])
.await
.is_ok()
} Try / catch
match rpc_task.await {
Err(e) => {
let msg = e.to_string();
if let Some(status) = msg.strip_prefix("Remote server exited with status ") {
// capture container logs / dmesg for OOM, run the binary manually to get the loader error
}
Err(e)
}
ok => ok,
} Prevention
- Match the server binary arch to the container platform before connecting
- Use base images with a recent glibc/musl
- Set sane container memory limits and monitor OOMKilled so the server is not killed
When it happens
Trigger: handle_rpc_messages_over_child_process_stdio observes the child exit with status != 0: dynamic linker failures (glibc/musl mismatch), wrong architecture binary, missing shared libraries, immediate crash on startup, or the container OOM-killing the process.
Common situations: x86_64 server binary inside an arm64 container (or vice versa, e.g. Apple Silicon host with amd64 image); very old glibc in the base image versus a newly built server; scratch images with no libc; container memory limits killing the server mid-session.
Related errors
- {output} error: process exited before debugger attached.
- zig not found on $PATH, install zig (see https://ziglang.org
- Neither curl nor wget is available
- Prebuilt remote servers are not yet available for windows-{a
- ZED_BUILD_REMOTE_SERVER is not set and no remote server exis
AI-assisted analysis of zed-industries/zed@5a9b9558db (2026-08-20).
Data as JSON: /api/errors/466d583230608f63.
Report an issue: GitHub.