gitbutlerapp/gitbutler · error
None of the MCP client's filesystem roots identify a Git rep
Error message
None of the MCP client's filesystem roots identify a Git repository. {} What it means
After probing every root with open_repository (crates/but/src/command/mcp/mod.rs:535), none opened as a Git repository (or the root URI was not a valid file URI); each failure string is collected and joined into the message. The client's roots exist but none is, or sits above, a usable .git worktree.
Source
Thrown at crates/but/src/command/mcp/mod.rs:535
);
}
let mut failures = Vec::new();
for root in roots {
let path = match root_path(root) {
Ok(path) => path,
Err(err) => {
failures.push(err.to_string());
continue;
}
};
match open_repository(&path) {
Ok(resolved) => return Ok(resolved),
Err(err) => failures.push(format!("{}: {err:#}", path.display())),
}
}
bail!(
"None of the MCP client's filesystem roots identify a Git repository. {}",
failures.join("; ")
)
}
fn root_path(root: &Root) -> Result<PathBuf> {
let url = Url::parse(&root.uri)
.with_context(|| format!("MCP root is not a valid URI: {}", root.uri))?;
url.to_file_path()
.map_err(|()| anyhow::anyhow!("MCP root is not a file URI: {}", root.uri))
}
fn open_repository(repository: &Path) -> Result<ResolvedRepository> {
let repository = repository
.canonicalize()
.with_context(|| format!("Could not resolve repository at {}", repository.display()))?;
let ctx = but_ctx::Context::discover(&repository)
.with_context(|| format!("Could not open repository at {}", repository.display()))?;View on GitHub (pinned to caf1f223d3)
Solutions
- Add a directory that is (or contains) a Git worktree as a root.
- Pass the `repository` path argument directly.
- Read the joined failure list in the message to see which root failed and why (invalid URI vs. not a repository).
Example fix
// before: root = file:///home/user/documents (no repo)
// after: root = file:///home/user/documents/project (contains .git)
// or
{ "repository": "/home/user/documents/project", ... } Defensive patterns
Strategy: validation
Validate before calling
for root in roots {
let path = Url::parse(&root.uri)?.to_file_path().map_err(|()| anyhow::anyhow!("not a file URI"))?;
if gix::open(&path).map(|r| r.is_worktree()).unwrap_or(false) {
return Ok(path); // a probe-able root exists
}
}
anyhow::bail!("no root is a git repository; pass repository explicitly"); Try / catch
match resolve_repository(None, context).await {
Err(err) if err.to_string().contains("identify a Git repository") => {
// parse the per-root failure details and retry with an explicit path
}
other => other,
} Prevention
- Open the folder that is the repository (or its parent) as the client root.
- Pass `repository` explicitly when roots are cloud or non-file URIs.
- Read the joined failure details — they distinguish invalid URIs from missing .git.
When it happens
Trigger: All workspace roots are plain directories with no discoverable .git at or above them; a root is a non-file URI (remote scheme) that Url::to_file_path rejects; sandboxing hides .git from the server.
Common situations: Opened a parent folder of several projects where none is at a root level; cloud-hosted root URIs; permissions that block .git discovery.
Related errors
- No repository was provided and this MCP client does not expo
- The MCP client did not provide any filesystem roots. Pass th
- When using OpenAI in a bring your own key configuration, you
- textFromToolResult(result)
- The refreshed reviews were missing from the response.
AI-assisted analysis of gitbutlerapp/gitbutler@caf1f223d3 (2026-08-20).
Data as JSON: /api/errors/0b67d5a0cd11974e.
Report an issue: GitHub.