xai-org/grok-build · error
failed to read '{}': {}
Error message
failed to read '{}': {} What it means
For GitRef::Workdir, read_version_bytes performs std::fs::read on the joined workdir path and wraps any I/O failure with this message. It means the working-tree file could not be read — usually it does not exist, though permissions or I/O errors surface here too.
Source
Thrown at crates/codegen/xai-grok-workspace/src/session/git.rs:762
} else {
let GitRef::Treeish(base_ref) = base else {
return None;
};
let GitRef::Treeish(head_ref) = head else {
return None;
};
diff_compare(repo, base_ref, head_ref, merge_base, opts)
}
}
fn read_version_bytes(repo: &Repository, path: &str, version: &str) -> Result<Vec<u8>> {
match GitRef::parse(version) {
GitRef::Workdir => {
let full_path = repo
.workdir()
.ok_or_else(|| anyhow::anyhow!("cannot read working files from bare repository"))?
.join(path);
std::fs::read(&full_path)
.map_err(|e| anyhow::anyhow!("failed to read '{}': {}", path, e))
}
GitRef::Index => read_blob_from_index(repo, path),
GitRef::Treeish(refspec) => {
let obj = repo
.revparse_single(&refspec)
.map_err(|e| anyhow::anyhow!("'{}' is not a valid revision: {}", refspec, e))?;
let commit = obj
.peel_to_commit()
.map_err(|e| anyhow::anyhow!("'{}' does not refer to a commit: {}", refspec, e))?;
let tree = commit.tree()?;
read_blob_from_tree(repo, &tree, path)
}
}
}
/// Binary files return empty content with is_binary=true.
fn read_version_content(repo: &Repository, path: &str, version: &str) -> Result<(String, bool)> {
let bytes = read_version_bytes(repo, path, version)?;
match String::from_utf8(bytes) {View on GitHub (pinned to bc7f02eddd)
Solutions
- Check the file exists (Path::exists / `ls`) before reading
- Fall back to the index or HEAD version when the workdir copy is missing
- Restore the file (`git checkout -- <path>`) if it was accidentally deleted
- Wrap the read and surface the underlying io::Error so ENOENT vs EACCES can be handled distinctly
Example fix
// before
let bytes = read_version_bytes(&repo, "src/main.rs", "workdir")?; // file deleted
// after
let bytes = match read_version_bytes(&repo, "src/main.rs", "workdir") {
Ok(b) => b,
Err(e) if e.to_string().contains("failed to read") => {
read_version_bytes(&repo, "src/main.rs", "HEAD")? // last committed copy
}
Err(e) => return Err(e),
}; Defensive patterns
Strategy: fallback
Validate before calling
fn workdir_file_exists(repo: &git2::Repository, path: &str) -> bool {
repo.workdir().map(|w| w.join(path).is_file()).unwrap_or(false)
} Try / catch
let bytes = match read_version_bytes(repo, path, "workdir") {
Ok(b) => b,
Err(e) if e.to_string().contains("failed to read") => {
read_version_bytes(repo, path, "HEAD")? // committed fallback
}
Err(e) => return Err(e),
}; Prevention
- Check Path::is_file before reading workdir paths
- Distinguish ENOENT from EACCES by inspecting the wrapped io::Error
- Fall back to index/HEAD versions when the working copy is missing
When it happens
Trigger: Reading version 'workdir' for a path that was deleted from the working tree, never created, renamed, or is unreadable due to permissions or symlink issues.
Common situations: Session references a file the user deleted or moved on disk, cleanup removed the file, file locked by another process, or path casing mismatches on case-sensitive filesystems.
Related errors
- failed to open instrumentation log {:?}: {}
- path '{}' not found in commit: {}
- path '{}' not found in staging area
- cannot read working files from bare repository
- the probe's output did not drain within {DRAIN_GRACE:?}
AI-assisted analysis of xai-org/grok-build@bc7f02eddd (2026-08-31).
Data as JSON: /api/errors/73360778646ecde9.
Report an issue: GitHub.