xai-org/grok-build · error · io::Error
daemonize is only supported on Unix and Windows
Error message
daemonize is only supported on Unix and Windows
What it means
daemonize() detaches the current process into a background daemon. This is implemented with platform-specific APIs that exist only on Unix and Windows; on any other target (e.g. wasm32) the function is compiled to a stub that always returns io::ErrorKind::Unsupported with 'daemonize is only supported on Unix and Windows'.
Source
Thrown at crates/codegen/xai-grok-workspace-daemon/src/daemonize.rs:202
.create(true)
.append(true)
.open(log_path)?;
let handle = HANDLE(log.as_raw_handle());
// SAFETY: `handle` is a live file handle owned by `log`; SetStdHandle only
// records it as the process stdout/stderr. `forget(log)` keeps it open for
// the process lifetime (the std streams reference it now).
unsafe {
SetStdHandle(STD_OUTPUT_HANDLE, handle).map_err(io::Error::other)?;
SetStdHandle(STD_ERROR_HANDLE, handle).map_err(io::Error::other)?;
}
std::mem::forget(log);
Ok(())
}
#[cfg(not(any(unix, windows)))]
pub fn daemonize(_log_path: &Path) -> io::Result<()> {
Err(io::Error::new(
io::ErrorKind::Unsupported,
"daemonize is only supported on Unix and Windows",
))
}
/// `fork()`; the parent exits 0, the child returns `Ok(())` to continue.
#[cfg(unix)]
fn fork_and_exit_parent() -> io::Result<()> {
// SAFETY: only called pre-runtime while single-threaded, so the fork
// cannot strand another thread's lock in the child.
match unsafe { libc::fork() } {
-1 => Err(io::Error::last_os_error()),
0 => Ok(()),
_ => process::exit(0),
}
}
/// `OpenOptions` for a daemon-owned file (log or pidfile).View on GitHub (pinned to bc7f02eddd)
Solutions
- Build and run the daemon only on unix or windows targets (check cfg!(any(unix, windows)) before calling).
- Gate the daemonize call behind a compile-time cfg or runtime feature so unsupported targets skip daemonization.
- On unsupported targets, run the work directly in-process instead of daemonizing.
Example fix
// before
daemonize(&log_path)?;
// after
#[cfg(any(unix, windows))]
daemonize(&log_path)?;
#[cfg(not(any(unix, windows)))]
return Err("daemonize unsupported on this target".into()); Defensive patterns
Strategy: type-guard
Validate before calling
fn daemonize_supported() -> bool {
cfg!(any(unix, windows))
}
// only call daemonize when true Try / catch
match daemonize(&log_path) {
Ok(()) => { /* daemonized */ }
Err(e) if e.kind() == std::io::ErrorKind::Unsupported => {
eprintln!("daemonize unsupported here; running in foreground");
run_in_foreground()?;
}
Err(e) => return Err(e.into()),
} Prevention
- Gate daemonize calls behind #[cfg(any(unix, windows))]
- Add a CI build for non-unix/windows targets to catch the stub early
- Provide an explicit foreground-mode fallback in your supervisor code
When it happens
Trigger: Calling xai_grok_workspace_daemon::daemonize() (with any log_path) while compiled for a target other than unix or windows, such as wasm32-unknown-unknown or embedded targets.
Common situations: Cross-compiling the workspace daemon for wasm/browser or embedded targets where fork/detach APIs do not exist; building a universal abstraction layer that calls daemonize unconditionally.
Related errors
- process termination is only supported on Linux and Windows
- daemon RemoveWorktree failed: {e}
- e.error (daemon error message propagated via anyhow!)
AI-assisted analysis of xai-org/grok-build@bc7f02eddd (2026-08-31).
Data as JSON: /api/errors/649b4673e7cc9ab1.
Report an issue: GitHub.