sinelaw/fresh · error
rg exited with code
Error message
rg exited with code ${r.exit_code}: ${r.stderr} What it means
The live_grep plugin's `rg` provider shells out to ripgrep via editor.spawnProcess and throws this error whenever rg terminates with a status other than 0. Unlike the ag/git-grep/ack providers, this one only treats exit code 0 as success, so even ripgrep's benign 'no matches found' exit code 1 becomes an error. Non-zero codes also cover real failures such as exit 2 for an invalid regex pattern or unreadable files, with details in stderr.
Solutions
- If regex mode is on, fix the query pattern (escape special characters or use literal mode).
- If the query is simply a no-match, note this provider throws on exit 1 — fix the provider to accept `r.exit_code === 0 || r.exit_code === 1` like the ag/git-grep providers do.
- Run `rg <pattern>` manually in the target cwd and read stderr to see the exact ripgrep failure.
- Verify ripgrep is installed and up to date (`rg --version`).
Example fix
// before
if (r.exit_code === 0) {
return parseGrepOutput(r.stdout, maxResults, (msg) => editor.debug(msg)) as GrepMatch[];
}
// after
if (r.exit_code === 0 || r.exit_code === 1) {
// rg exits 1 when there are no matches — treat as empty.
return parseGrepOutput(r.stdout, maxResults, (msg) => editor.debug(msg)) as GrepMatch[];
} Defensive patterns
Strategy: try-catch
Validate before calling
if (regexMode) { try { new RegExp(query); } catch { throw new Error(`invalid regex: ${query}`); } }
if (typeof editor.spawnProcess !== "function") throw new Error("spawnProcess unavailable"); Type guard
function isGrepResult(r) { return typeof r === "object" && r !== null && typeof r.exit_code === "number" && typeof r.stdout === "string" && typeof r.stderr === "string"; } Try / catch
try {
const matches = await rgProvider.search(query, opts);
} catch (e) {
if (/rg exited with code 2/.test(String(e))) {
// invalid pattern — retry with literal mode
matches = await rgProvider.search(query, { ...opts, regex: false });
} else if (/rg exited with code 1/.test(String(e))) {
matches = []; // no matches surfaced as an error by this provider
} else {
throw e;
}
} Prevention
- Validate regex queries before enabling regex mode.
- Prefer backends whose no-match exit code (1) is handled; or patch the provider to accept exit 1.
- Keep ripgrep installed and in PATH.
- Test searches in the target cwd manually before automating.
When it happens
Trigger: Calling the live-grep search with the rg provider active when: (1) rg finds no matches (exit 1, not whitelisted here), (2) the query is an invalid regex while regex mode is on (rg exit 2), (3) rg is missing/broken enough to fail, or (4) the cwd is unreadable.
Common situations: Typing a regex query like '[' or 'a(' with regex mode enabled; searching a term that genuinely has no matches (because exit 1 is not handled as empty like the other providers); running in a directory rg cannot traverse; an rg version with different flag support causing argument errors.
Understand the failure class
Background: "git command failed": what it means when a tool shells out to git and git exits non-zero — this error's family across 21 libraries.
Related errors
- ag exited with code
- ack exited with code
- grep exited with code
- git grep exited with code
- ${provider.name}: ${e instanceof Error ? e.message …
AI-assisted analysis of sinelaw/fresh@67894ca546 (2026-09-13).
Data as JSON: /api/errors/fa3d3330428fca48.
Report an issue: GitHub.
Appendix: source
Thrown at crates/fresh-editor/plugins/live_grep.ts:472
"-g", "!.git",
];
if (regex === false) args.push("--fixed-strings");
if (wholeWord) args.push("--word-regexp");
if (includeIgnored) {
// Search ignored *and* hidden files (dotfiles). `.git` stays
// excluded via the glob above.
args.push("--no-ignore", "--hidden");
} else {
// Default: respect ignore files, plus prune the usual heavy
// build/vendor dirs and lockfiles that bury real hits.
args.push("-g", "!node_modules", "-g", "!target", "-g", "!*.lock");
}
args.push("--", query);
const r = await editor.spawnProcess("rg", args, cwd);
if (r.exit_code === 0) {
return parseGrepOutput(r.stdout, maxResults, (msg) => editor.debug(msg)) as GrepMatch[];
}
throw new Error(`rg exited with code ${r.exit_code}: ${r.stderr}`);
},
});
registerProvider({
name: "ag",
priority: -2,
isAvailable: async () => {
try {
const r = await editor.spawnProcess("ag", ["--version"], editor.getCwd());
return r.exit_code === 0;
} catch {
return false;
}
},
search: async (query, { cwd, maxResults, wholeWord, regex }) => {
const args = [
"--column",
"--numbers",View on GitHub (pinned to 67894ca546)