helix-editor/helix · warning · anyhow::Error
no diff provider returns success
Error message
no diff provider returns success
What it means
DiffProviderRegistry::for_each_changed_file runs every configured provider (git is the only built-in one) and uses find_map on their results. If no provider returned Ok — in practice, because gix failed to discover or open a repository for the cwd ('failed to discover git repo' when the directory is not inside any git repository, or an open/status failure on a corrupt .git) — the fallback callback is invoked with Err('no diff provider returns success'). Consumers surface it via status::report_blocking, e.g. the changed-files picker shows it in the statusline.
Source
Thrown at helix-vcs/src/lib.rs:79
})
}
/// Fire-and-forget changed file iteration. Runs everything in a background task. Keeps
/// iteration until `on_change` returns `false`.
pub fn for_each_changed_file(
self,
cwd: PathBuf,
trust_full: bool,
f: impl Fn(Result<FileChange>) -> bool + Send + 'static,
) {
tokio::task::spawn_blocking(move || {
if self
.providers
.iter()
.find_map(|provider| provider.for_each_changed_file(&cwd, trust_full, &f).ok())
.is_none()
{
f(Err(anyhow!("no diff provider returns success")));
}
});
}
}
impl Default for DiffProviderRegistry {
fn default() -> Self {
// currently only git is supported
// TODO make this configurable when more providers are added
let providers = vec![
#[cfg(feature = "git")]
DiffProvider::Git,
DiffProvider::None,
];
DiffProviderRegistry { providers }
}
}
View on GitHub (pinned to 079a789e8c)
Solutions
- If the project is not under git, initialize or ignore the message — the picker just has nothing to list.
- Verify `git status` runs cleanly in the same directory from a terminal; if it errors, repair the repository (e.g. `git fsck`, restore .git/config).
- For non-git projects wanting picker parity, put the project under git (git init) or accept the empty picker.
Defensive patterns
Strategy: try-catch
Validate before calling
// preflight: is the cwd inside a git repo at all?
let in_repo = gix::discover::upward_opts(
&cwd,
gix::discover::upwards::Options { dot_git_only: true, ..Default::default() },
).is_ok();
if !in_repo { /* skip the changed-files picker / expect the fallback error */ } Try / catch
// the registry already funnels every provider failure into one Err callback
cx.editor.diff_providers.clone().for_each_changed_file(cwd, trust, move |res| match res {
Ok(change) => injector.push(change).is_ok(),
Err(err) => { status::report_blocking(err); true } // degrade gracefully: empty picker
}); Prevention
- Expect this error on non-git projects — VCS integration is git-only today.
- Run `git status` once in a project before wiring tooling on top of the changed-files API.
- Treat provider failure as 'no data', not fatal: keep the picker functional with zero rows.
When it happens
Trigger: Opening the changed-files picker (default `space` g) in a directory that is not inside any git repository; a corrupted/unreadable .git directory; a repo gix cannot open due to discovery errors.
Common situations: Using helix on non-git projects (the most common case — no VCS integration is configured for them); broken .git dirs after interrupted operations; repos with unreadable config.
Related errors
AI-assisted analysis of helix-editor/helix@079a789e8c (2026-08-16).
Data as JSON: /api/errors/02d10a7a14b9286a.
Report an issue: GitHub.