Bundled ugrep (Bash `grep` shim) balloons to 14–16.6 GB RSS on bounded-repeat -o patterns that GNU grep handles in 3 MB — repeated OOM kills on a production box

Status Closed — duplicate
Reported on v2.1.205
Maintainer reply None cached
Activity 1 comment · opened Jul 18, 2026 · closed Aug 17, 2026

Environment

  • Claude Code versions observed: 2.1.205, 2.1.207, 2.1.212, 2.1.214 (headless claude -p sessions)
  • OS: Amazon Linux (EC2 m7a.2xlarge, 8 vCPU / 30 GiB, no swap)
  • The Bash tool's shell snapshot defines a grep function that re-execs the Claude binary as ugrep:

function grep { ... ARGV0=ugrep "$_cc_bin" -G --ignore-files --hidden -I --exclude-dir=.git ... "$@" }
so every grep an agent runs in the Bash tool is the bundled ugrep engine.

Bug

Bounded-repeat context-extraction patterns with -o, e.g.:

grep -h -o '.\{0,80\}7,400,000.\{0,200\}' notes-*.md

against ordinary markdown/log files containing long single lines (our repro file: 11 KB, 32 lines, longest line ~1,950 chars) cause the bundled ugrep to allocate unboundedly — observed 14.4–16.6 GB anon RSS. The process also does not fail fast: with cgroup memory throttling it held ~16.5 GB for 69+ minutes without completing or erroring (it appears to hang while buffering, so the invocation never returns to the agent).

Impact

Four kernel OOM kills in five days on one production box (kernel OOM dumps show the re-exec'd version binary — argv[0] renders as e.g. 2.1.214 — alone at 3.6–4.2M pages; next-largest process ~90 MB). Each kill took down a long-running headless session mid-task.

Reproduction

  1. Create a markdown file with a few multi-KB single lines (ours was 11 KB total).
  2. In a Claude Code Bash tool shell (so the grep shim applies), run:

ulimit -v 524288; grep -o '.\{0,80\}SOME_STRING.\{0,200\}' file.md

  1. Observed: core dump within seconds at the 512 MB cap (unbounded: grows to 14–16+ GB).

Comparison (same pattern, same files)

  • GNU grep 3.8 (/usr/bin/grep): completes instantly, max RSS 2,960 KB (measured with /usr/bin/time -v).
  • ripgrep 15.1.0: handles it fine (its regex engine enforces a compiled-size limit and errors rather than ballooning).

Expected

Either bounded memory for bounded-repeat patterns, a hard compile/size limit with a fast error (rust-regex-style), or at minimum fail-fast rather than an indefinite multi-GB hang — an agent-driven tool will eventually emit pathological patterns, and one bad grep currently OOMs the host.

Workarounds we deployed

  • PreToolUse hook refusing/rewriting bounded-repeat -o grep patterns; prescribing rg or command grep for extraction work.
  • cgroup MemoryMax + OOMPolicy=continue on the service as blast-radius control.

View original on GitHub ↗

This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗