xai-org/grok-build · warning · std::io::Error

<invalid u64 in memory.current>

Error message

<invalid u64 in memory.current>

What it means

memory_current reads the cgroup's memory.current file and parses its trimmed contents as u64; if the parse fails it wraps the ParseIntError in an io::Error with InvalidData. The message "<invalid u64 in memory.current>" indicates the kernel-reported value could not be interpreted as an unsigned 64-bit integer.

Source

Thrown at crates/codegen/xai-grok-tools/src/computer/local/cgroup.rs:243

                "Created cgroup with memory limits"
            );

            Ok(CgroupHandle { fs_path })
        }

        /// Move a process (by PID) into this cgroup.
        pub(crate) async fn add_process(&self, pid: u32) -> std::io::Result<()> {
            let procs_path = self.fs_path.join("cgroup.procs");
            tokio::fs::write(&procs_path, pid.to_string()).await
        }

        /// Read `memory.current` from this cgroup.
        #[allow(dead_code)]
        pub(crate) async fn memory_current(&self) -> std::io::Result<u64> {
            let s: String = tokio::fs::read_to_string(self.fs_path.join("memory.current")).await?;
            s.trim()
                .parse::<u64>()
                .map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, e))
        }

        /// Filesystem path to this cgroup.
        pub(crate) fn path(&self) -> &std::path::Path {
            &self.fs_path
        }
    }

    impl Drop for CgroupHandle {
        fn drop(&mut self) {
            let path = self.fs_path.clone();
            // Always use tokio::spawn: the cleanup future is Send and Drop
            // can fire after the LocalSet has shut down, making spawn_local
            // unsafe here.
            tokio::spawn(async move {
                let kill_path = path.join("cgroup.kill");
                let _ = tokio::fs::write(&kill_path, "1").await;
                tokio::time::sleep(std::time::Duration::from_millis(50)).await;

View on GitHub (pinned to bc7f02eddd)

Solutions

  1. Verify fs_path points to an actual cgroupv2 directory containing a valid memory.current file.
  2. cat the file manually to inspect its contents for non-numeric values like "max" or empty output.
  3. Add a fallback (return None / a sentinel) when parsing fails so monitoring code treats it as an unreadable gauge rather than an error.
  4. Retry after a short delay if the cgroup is being created/destroyed concurrently.

Example fix

// before
let bytes = cgroup.memory_current()?;
// after
let bytes = match cgroup.memory_current() {
    Ok(b) => b,
    Err(e) if e.kind() == std::io::ErrorKind::InvalidData => {
        tracing::warn!("memory.current unreadable; skipping sample");
        0
    }
    Err(e) => return Err(e),
};
Defensive patterns

Strategy: try-catch

Validate before calling

let raw = tokio::fs::read_to_string(cgroup.path().join("memory.current")).await?;
let valid = raw.trim().parse::<u64>().is_ok();

Try / catch

match cgroup.memory_current().await {
    Ok(v) => v,
    Err(e) if e.kind() == std::io::ErrorKind::InvalidData => 0, // skip sample
    Err(e) => return Err(e.into()),
}

Prevention

When it happens

Trigger: memory.current containing "max", an empty string, or non-numeric bytes — e.g. reading from a wrong/placeholder cgroup path, a mocked or virtualized filesystem, or a file truncated to garbage.

Common situations: Pointing fs_path at a directory that is not a real cgroup; tests stubbing memory.current with placeholder text; container runtimes exposing nonstandard cgroup files; race where the cgroup directory is being torn down and reads return partial data.

Related errors


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