xai-org/grok-build · error · io::Error

{}

Error message

{}

What it means

After computing the parent and serializing the TrustDocument to TOML, persist_doc maps serde/serialization failures into io::ErrorKind::InvalidData. It means the in-memory document could not be rendered as TOML (e.g. a value type not representable in TOML).

Source

Thrown at crates/codegen/xai-grok-workspace/src/trust.rs:338

    /// Uses a unique temp file in the destination directory so concurrent
    /// writers never share a temp path, fsyncs it for crash durability, then
    /// renames it over the destination. `tempfile::NamedTempFile` creates the
    /// temp with `O_EXCL` and `0600` permissions on Unix, and `persist`
    /// performs an atomic replace (including over an existing destination on
    /// Windows).
    fn persist_doc(path: &Path, doc: &TrustDocument) -> io::Result<()> {
        use std::io::Write;

        let parent = path.parent().ok_or_else(|| {
            io::Error::new(
                io::ErrorKind::InvalidInput,
                "trust store path has no parent",
            )
        })?;
        std::fs::create_dir_all(parent)?;

        let body = toml::to_string_pretty(doc)
            .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;

        // Unique temp in the same directory (atomic rename requires same FS).
        let mut tmp = tempfile::NamedTempFile::new_in(parent)?;
        tmp.write_all(body.as_bytes())?;
        // Durably flush to disk before publishing so a crash can't leave a
        // zero-length or stale store behind. (`File::flush` is a no-op for
        // durability; `sync_all` is what guarantees the bytes hit disk.)
        tmp.as_file().sync_all()?;
        // Atomic publish.
        tmp.persist(path).map_err(|e| e.error)?;
        Ok(())
    }
}

/// Compute the trust **workspace key** for a working directory.
///
/// The key is the canonicalized git repository root when `cwd` is inside a
/// repo (trust applies to the whole repo), otherwise the canonicalized `cwd`.

View on GitHub (pinned to bc7f02eddd)

Solutions

  1. Inspect the serde error (it is the io error's source) to find the offending field
  2. Change the field type to a TOML-compatible one (string-keyed maps, finite floats)
  3. Round-trip the document through a test toml::to_string_pretty call in CI to catch regressions

Example fix

// before
extra: BTreeMap<MyKey, String>, // MyKey doesn't serialize as a TOML table key
// after
extra: BTreeMap<String, String>,
Defensive patterns

Strategy: try-catch

Validate before calling

fn toml_representable(doc: &TrustDocument) -> bool {
    toml::to_string_pretty(doc).is_ok()
}
assert!(toml_representable(&doc), "document must round-trip as TOML");

Try / catch

if let Err(e) = persist_doc(&path, &doc) {
    if e.kind() == io::ErrorKind::InvalidData {
        eprintln!("TOML serialize failed: {}", e.source().map(|s| s.to_string()).unwrap_or_default());
    }
    return Err(e.into());
}

Prevention

When it happens

Trigger: Calling the persist API with a TrustDocument containing a field TOML cannot represent (e.g. nested map keys that aren't strings, NaN/Infinity floats, unsupported enum representations).

Common situations: Adding a new field to TrustDocument with a type the toml crate can't serialize; storing heterogeneous maps; deserializing input from JSON and re-serializing to TOML.

Related errors


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