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

invalid magic

Error message

invalid magic

What it means

read_from deserializes a binary-persisted workspace file-system index. The first 4 bytes of the stream must equal MAGIC_INDEX; if they don't, the data is not a valid index file and read_from fails with io::ErrorKind::InvalidData, 'invalid magic'.

Source

Thrown at crates/codegen/xai-grok-workspace/src/file_system/index.rs:902

                w.write_all(&seg_id.as_u32().to_le_bytes())?;
            }
        }

        Ok(())
    }

    /// Deserialize from binary format.
    pub fn from_bytes(data: &[u8]) -> io::Result<Self> {
        Self::read_from(&mut io::Cursor::new(data))
    }

    /// Read from a reader in binary format.
    pub fn read_from<R: Read>(r: &mut R) -> io::Result<Self> {
        // Header
        let mut magic = [0u8; 4];
        r.read_exact(&mut magic)?;
        if &magic != MAGIC_INDEX {
            return Err(io::Error::new(io::ErrorKind::InvalidData, "invalid magic"));
        }

        let mut buf2 = [0u8; 2];
        let mut buf4 = [0u8; 4];

        r.read_exact(&mut buf2)?;
        let version = u16::from_le_bytes(buf2);
        if version != VERSION {
            return Err(io::Error::new(
                io::ErrorKind::InvalidData,
                format!("unsupported version: {}", version),
            ));
        }

        r.read_exact(&mut buf2)?;
        let flags = u16::from_le_bytes(buf2);

        // Handle compression

View on GitHub (pinned to bc7f02eddd)

Solutions

  1. Verify you are opening the correct index file at the expected path.
  2. Check the file is at least 4 bytes and inspect its header bytes against the expected magic before loading.
  3. Regenerate the index (delete the corrupt file and let the workspace rebuild it) instead of loading a corrupt one.
  4. Restore the file from a backup if it was corrupted on disk.

Example fix

// before
let idx = Index::read_from(&mut file)?;
// after
let mut magic = [0u8; 4];
file.read_exact(&mut magic)?;
if &magic != MAGIC_INDEX {
    // rebuild instead of failing
    return Index::rebuild(&workspace_root);
}
let idx = Index::read_from(&mut file)?;
Defensive patterns

Strategy: validation

Validate before calling

fn looks_like_index(path: &std::path::Path) -> std::io::Result<bool> {
    use std::io::Read;
    let mut f = std::fs::File::open(path)?;
    let mut magic = [0u8; 4];
    match f.read_exact(&mut magic) {
        Ok(()) => Ok(&magic == MAGIC_INDEX),
        Err(_) => Ok(false), // too short
    }
}

Try / catch

match Index::read_from(&mut file) {
    Ok(i) => i,
    Err(e) if e.kind() == std::io::ErrorKind::InvalidData && e.to_string() == "invalid magic" => {
        Index::rebuild(&workspace_root)?
    }
    Err(e) => return Err(e.into()),
}

Prevention

When it happens

Trigger: Calling Index::read_from on a file/stream whose first 4 bytes are not the index magic: an empty file, a file written by a different tool, a corrupted/truncated header, or pointing read_from at a wrong (non-index) file.

Common situations: Opening a stale or corrupted workspace index file after a crash; passing the wrong file path to a loader; reading a file that was replaced or zero-length.

Related errors


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