sinelaw/fresh · critical
no search backend available — install ripgrep, or register…
Error message
no search backend available — install ripgrep, or register a provider via init.ts (`editor.getPluginApi("live-grep")?.registerProvider(...)`). What it means
The live_grep fan-out search throws this when the file scope is enabled but searchFiles returns null — meaning no grep backend (ripgrep, ag, git grep, ack, grep, or a registered provider) could be found at all — AND the buffers and diagnostics scopes are disabled, so there is literally nothing to search. The plugin treats a missing backend as tolerable only when other scopes can still produce results.
Solutions
- Install ripgrep (`brew install ripgrep`, `apt install ripgrep`, `winget install BurntSushi.ripgrep`) — the primary backend.
- Or register a custom provider at startup via `editor.getPluginApi("live-grep")?.registerProvider(...)` in init.ts, as the message instructs.
- Enable the buffers and/or diagnostics scopes so a missing file backend is not fatal.
- Check that the editor's spawn environment PATH includes the directory containing your grep tools.
Example fix
// before (init.ts) — nothing registered, no ripgrep installed
// after
editor.getPluginApi("live-grep")?.registerProvider({
name: "custom-grep",
priority: 0,
search: async (query, opts) => {
/* call your own search binary */
return [];
},
}); Defensive patterns
Strategy: fallback
Validate before calling
async function hasGrepBackend(editor, cwd) {
for (const b of ["rg", "ag", "git", "ack", "grep"]) {
try { await editor.spawnProcess(b, ["--version"], cwd); return true; } catch {}
}
return false;
}
// before searching with only the files scope: if (!(await hasGrepBackend(editor, cwd))) install ripgrep or enable other scopes; Type guard
null
Try / catch
try {
await liveGrep.search(query);
} catch (e) {
if (/no search backend available/.test(String(e))) {
// degrade: retry with buffers scope enabled, or prompt the user to install ripgrep
await liveGrep.search(query, { scopes: { files: false, buffers: true, diagnostics: true } });
} else { throw e; }
} Prevention
- Install ripgrep in every environment where the editor runs (containers, CI, minimal images).
- Keep at least one non-file scope (buffers/diagnostics) enabled as a safety net.
- Register a custom provider in init.ts for restricted environments without grep tools.
- Verify PATH inside the editor's spawn environment includes tool directories.
When it happens
Trigger: Running a live-grep search with the files (or ignored) scope enabled on a machine where none of rg/ag/git/ack/grep binaries are locatable by spawnProcess, while both the buffers and diagnostics scopes are turned off in scopeEnabled.
Common situations: Fresh containers/CI images or minimal Windows/macOS installs with no grep-family tool in PATH; users disabling all scopes except files after uninstalling ripgrep; wrong PATH inside the editor's spawn environment so binaries aren't found even though installed.
Understand the failure class
Background: "not installed", "pip install", "required for": how missing-dependency errors surface across open-source libraries — this error's family across 34 libraries.
Related errors
- rg exited with code
- ag exited with code
- git grep exited with code
- ack exited with code
- grep exited with code
AI-assisted analysis of sinelaw/fresh@67894ca546 (2026-09-13).
Data as JSON: /api/errors/9679eb05025c6cd5.
Report an issue: GitHub.
Appendix: source
Thrown at crates/fresh-editor/plugins/live_grep.ts:991
throw new Error(`${provider.name}: ${e instanceof Error ? e.message : String(e)}`);
}
}
// Fan the query out across every enabled scope and merge into one
// capped, tagged result list. Order is files → buffers → diagnostics
// so the most common hits lead.
async function search(query: string): Promise<GrepMatch[]> {
lastQuery = query;
const wasTruncated = lastSearchTruncated;
const results: GrepMatch[] = [];
const remaining = () => MAX_RESULTS - results.length;
if (scopeEnabled.files || scopeEnabled.ignored) {
const fileMatches = await searchFiles(query);
if (fileMatches === null) {
// No grep backend. Only fatal if there's nothing else to search.
if (!scopeEnabled.buffers && !scopeEnabled.diagnostics) {
throw new Error(
"no search backend available — install ripgrep, or register a provider via init.ts (`editor.getPluginApi(\"live-grep\")?.registerProvider(...)`)."
);
}
} else {
for (const m of fileMatches) {
if (results.length >= MAX_RESULTS) break;
results.push(m);
}
}
}
if (scopeEnabled.buffers && remaining() > 0) {
const filesActive = scopeEnabled.files || scopeEnabled.ignored;
results.push(...await searchOpenBuffers(query, remaining(), !filesActive));
}
if (scopeEnabled.terminals && remaining() > 0) {
results.push(...await searchTerminals(query, remaining()));View on GitHub (pinned to 67894ca546)