xai-org/grok-build · error

cannot read working files from bare repository

Error message

cannot read working files from bare repository

What it means

read_version_bytes serves GitRef::Workdir by joining the repo workdir with the relative path and reading from disk. Bare repositories have no working directory, so repo.workdir() is None and this error is thrown instead of attempting a filesystem read that cannot succeed.

Source

Thrown at crates/codegen/xai-grok-workspace/src/session/git.rs:759

) -> Option<git2::Diff<'a>> {
    if base.is_working_state() || head.is_working_state() {
        diff_working_state(repo, base, head, opts)
    } 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.

View on GitHub (pinned to bc7f02eddd)

Solutions

  1. Use a non-bare clone with a working tree for session content reads
  2. Read a committed version instead: use GitRef::Treeish (e.g. HEAD) or GitRef::Index
  3. If bare operation is required, materialize content via `git show HEAD:<path>` equivalent (tree/blob reads)
  4. Match on this error and return a clear 'no working files available' result to the caller

Example fix

// before
let bytes = read_version_bytes(&repo, "src/main.rs", "workdir")?; // bare repo
// after
let bytes = match read_version_bytes(&repo, "src/main.rs", "workdir") {
    Ok(b) => b,
    Err(e) if e.to_string().contains("bare repository") => {
        read_version_bytes(&repo, "src/main.rs", "HEAD")? // fall back to committed version
    }
    Err(e) => return Err(e),
};
Defensive patterns

Strategy: fallback

Validate before calling

fn workdir_readable(repo: &git2::Repository) -> Option<std::path::PathBuf> {
    if repo.is_bare() { None } else { repo.workdir().map(|p| p.to_path_buf()) }
}

Type guard

fn is_bare(repo: &git2::Repository) -> bool { repo.is_bare() }

Try / catch

match read_version_bytes(repo, path, "workdir") {
    Ok(b) => b,
    Err(e) if e.to_string().contains("bare repository") => {
        read_version_bytes(repo, path, "HEAD")? // committed content instead
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling read_version_content with version 'workdir' (or the default workdir variant) on a repository discovered as bare — e.g. after discover_git_root flagged a bare repo but the read was still attempted.

Common situations: Workspace pointed at a bare server-side clone, a --bare CI checkout, or session metadata persisting a path that later became bare; also GIT_DIR tricks that hide the worktree.

Related errors


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