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

  1. Build and run the daemon only on unix or windows targets (check cfg!(any(unix, windows)) before calling).
  2. Gate the daemonize call behind a compile-time cfg or runtime feature so unsupported targets skip daemonization.
  3. 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

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


AI-assisted analysis of xai-org/grok-build@bc7f02eddd (2026-08-31). Data as JSON: /api/errors/649b4673e7cc9ab1. Report an issue: GitHub.