sinelaw/fresh · error
ag exited with code
Error message
ag exited with code ${r.exit_code}: ${r.stderr} What it means
The live_grep plugin's `ag` (the_silver_searcher) provider throws this when the spawned ag process exits with a code other than 0 or 1 (1 means 'no matches' and is handled as an empty result). Codes like 2 indicate ag itself failed — typically a bad regex, bad flags, or an unusable search directory. The stderr text appended to the message carries ag's own diagnostic.
Solutions
- Fix the query pattern if regex mode is enabled (validate or escape it).
- Run `ag <pattern>` by hand in the same cwd and read stderr for the underlying cause.
- Confirm ag is installed and reasonably current (`ag --version`); upgrade if flags are unsupported.
- Prefer the ripgrep provider (higher priority) if ag keeps failing.
Example fix
// before
const r = await editor.spawnProcess("ag", args, cwd);
// after
// validate the regex before spawning when regex mode is on
if (regex) { try { new RegExp(query); } catch (e) { throw new Error(`invalid pattern: ${query}`); } }
const r = await editor.spawnProcess("ag", args, cwd); Defensive patterns
Strategy: try-catch
Validate before calling
if (regexMode) { try { new RegExp(query); } catch { throw new Error(`invalid regex: ${query}`); } }
await editor.spawnProcess("ag", ["--version"], cwd); // backend present check Type guard
function isSpawnResult(r) { return r && typeof r.exit_code === "number" && typeof r.stderr === "string"; } Try / catch
try {
results = await agProvider.search(query, opts);
} catch (e) {
if (/ag exited with code/.test(String(e))) {
results = await rgProvider.search(query, opts); // fall back to another backend
} else { throw e; }
} Prevention
- Verify `ag --version` works in the target environment before relying on this provider.
- Escape or validate user regex input in regex mode.
- Confirm the search cwd exists and is readable.
- Keep a higher-priority provider (ripgrep) installed so ag is not required.
When it happens
Trigger: Invoking the live-grep ag provider when: (1) the query is an invalid regex in regex mode (ag exits 2), (2) an unsupported flag combination is passed (wholeWord/wholePath variants on unusual ag versions), or (3) the cwd is missing or unreadable.
Common situations: Ag not installed properly or an old version lacking flags like --word-regexp/--literal; typing malformed regex like '(' with regex mode on; searching from a deleted or unreadable working directory.
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
- rg 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/6c3266b6ed32632b.
Report an issue: GitHub.
Appendix: source
Thrown at crates/fresh-editor/plugins/live_grep.ts:506
const args = [
"--column",
"--numbers",
"--nogroup",
"--nocolor",
"--smart-case",
"--ignore", ".git",
"--ignore", "node_modules",
"--ignore", "target",
"--ignore", "*.lock",
];
if (regex === false) args.push("--literal");
if (wholeWord) args.push("--word-regexp");
args.push("--", query);
const r = await editor.spawnProcess("ag", args, cwd);
if (r.exit_code === 0 || r.exit_code === 1) {
return parseGrepOutput(r.stdout, maxResults, (msg) => editor.debug(msg)) as GrepMatch[];
}
throw new Error(`ag exited with code ${r.exit_code}: ${r.stderr}`);
},
});
/** The cwd git-grep should run in: the caller's `preferred` cwd when it is
* itself inside a repo, else the active buffer's dir (monorepo: the workspace
* root isn't a repo but the open file is). Returns null when neither is a
* repo. Used by both `isAvailable` and `search` so they can't disagree. */
async function gitGrepCwd(preferred: string): Promise<string | null> {
const inRepo = await editor.spawnProcess(
"git", ["rev-parse", "--is-inside-work-tree"], preferred
);
if (inRepo.exit_code === 0) return preferred;
const cand = gitCwdCandidate(editor);
if (cand !== preferred) {
const r = await editor.spawnProcess(
"git", ["rev-parse", "--is-inside-work-tree"], cand
);
if (r.exit_code === 0) return cand;View on GitHub (pinned to 67894ca546)