Cursor Agent CLI crash on Linux x86_64 (Herdr)

Where does the bug appear (feature/product)?

Cursor CLI

Describe the Bug

cursor-agent version 2026.09.18-9a7762b intermittently hard-crashes on Linux x86_64 while the Ink/React TUI redraws large ANSI-styled or syntax-highlighted terminal output. Fatal outcomes observed: Illegal instruction and Segmentation fault.

Same agent version in Herdr on macOS arm64 does not crash under normal use.

Already latest: cursor-agent update says Already up to date. Clearing ~/.cache/cursor-compile-cache did not help.

Environment details:

Broken host: Linux x86_64 LXC (Proxmox 6.8.12-43-pve), CPU Intel Core i7-10710U
Working host: macOS 26.6.2 arm64, same agent version
Multiplexer: Herdr 0.9.1 on both hosts (agent runs in a Herdr pane PTY)
Remote attach: SSH to Herdr; SemanticFrame seen (example cols=209 rows=43)
Remote color env: TERM=dumb, COLORTERM unset

Crash site is Ink ANSI style merge while painting a large string (about 13k chars), inside Cursor bundled Node, not Herdr Rust code. Herdr then shows pane agent going from Cursor to None. On the Linux host, herdr.service has also died in the same window with SIGBUS / SIGSEGV under agent load (memory peak about 1.2 to 2.6 GiB).

Stack frames include: B(aka B) style merge (endCode / code Sets), get (screen buffer), onImmediateRender / Yoga layout, React commit (Bs/bs/as/os), processImmediate.

Source snippet from the crash:

function B(e,t){
const r=new Set(t.map((e=>e.endCode))),
n=new Set(t.map((e=>e.code))),
s=new Set(e.map((e=>e.code)));
return[…(i=e.filter((e=>v(e)?!n.has(e.code):!r.has(e.endCode))),
function(e){return b(,e)}(i).reverse().map((e=>({…e,code:e.endCode})))),
…t.filter((e=>!s.has(e.code)))];var i
}

Binary path: ~/.local/share/cursor-agent/versions/2026.09.18-9a7762b/index.js
Terminal ends with: Illegal instruction
Full stacktrace available (includes String[13289] and JSArray[208] of ANSI tokens).

Workarounds: avoid huge highlighted dumps in the live TUI; NO_COLOR=1; or agent -p / non-interactive print mode.

Steps to Reproduce

  1. On Linux x86_64, run Herdr 0.9.1 headless and attach the TUI (local or over SSH).
  2. In a pane, start interactive cursor-agent / agent version 2026.09.18-9a7762b.
  3. Drive a session that causes large syntax-highlighted or heavily ANSI-colored TUI redraws (large file dumps, big diffs, long colored tool output).
  4. Observe hard crash (Illegal instruction or Segmentation fault); pane agent disappears.

Control: same steps on macOS arm64 Herdr with the same agent version — no crash.
Intermittent, but happens semi-regularly under heavy highlighted redraws.

Expected Behavior

Agent TUI stays stable when rendering highlighted code, diffs, or long tool output in a Herdr pane on Linux x86_64. No Illegal instruction or Segmentation fault.

Operating System

Linux

Version Information

CLI: cursor-agent / agent 2026.09.18-9a7762b
Not an IDE crash; IDE version N/A for the failing path
Herdr (host multiplexer): 0.9.1
Bundled Node: the agent-shipped Linux x64 node under ~/.local/share/cursor-agent/versions/2026.09.18-9a7762b/node

For AI issues: which model did you use?

Not model-specific.

For AI issues: add Request ID with privacy disabled

N/A

Additional Information

Same agent version: works in Herdr on macOS arm64; crashes in Herdr on Linux x86_64.
Looks platform-specific to the Linux x86_64 agent build / Ink redraw path under large highlighted output.
After crash, Herdr pane agent clears (Cursor to None). Sometimes herdr.service itself exits with SIGBUS or SIGSEGV in the same timeframe.
cursor-agent update reports Already up to date.
Workarounds reduce exposure but do not fix the crash.

Does this stop you from using Cursor

Sometimes - I can sometimes use Cursor

Hey, thanks for the detailed report and stack trace, that really helps.

From the trace, this doesn’t look like a CPU or instruction set issue. The frame where it crashes is plain JavaScript in the terminal renderer, and the String[...] and JSArray[...] annotations are what Node prints when the process runs out of JavaScript heap. That also explains why Linux is affected but macOS isn’t. Node picks the heap limit based on the memory it can see, and inside an LXC container that’s usually much lower than on a desktop Mac. The fact that herdr.service in the same window crashes with SIGBUS or SIGSEGV also points to container-wide memory pressure.

To confirm this and dig further, two things:

  1. In the same terminal, scroll a bit above the stack trace and paste the lines starting with <--- Last few GCs ---> and FATAL ERROR: if they exist. That confirms OOM in one paste.
  2. Also send the output of free -m from the Linux host. I want to understand the container’s real memory ceiling.

For now, raising the heap ceiling should stop the crashes. Pick a value that fits into the container RAM:

NODE_OPTIONS=--max-old-space-size=4096 cursor-agent

This same workaround helped in a similar case: OOM in cli (please reduce the title limit)

Memory usage grows most in long sessions with lots of highlighted output like big file dumps, large diffs, and long colored tool output, so starting a fresh session can also help for very long runs. Your workarounds NO_COLOR=1 and agent -p reduce exposure for the same reason. Let me know if it still crashes with the increased limit.

Agreed this is Node heap / OOM on the Linux host (default heap_size_limit ~2240 MiB on an 8 GiB CT), not an ISA / Ink-only bug. The V8 stack we pasted is just where the process was when it died (TUI redraw of a large ANSI string), not a separate root cause.

Retest: after setting NODE_OPTIONS=–max-old-space-size=4096 it still hard-crashed once (Illegal instruction / Segmentation fault, same Ink render frames). On that run NODE_OPTIONS was likely still unset in the Herdr pane (bashrc/environment.d not inherited by the agent launcher). I have since wrapped ~/.local/bin/agent and cursor-agent so every start forces --max-old-space-size=4096, and will retest from a fresh pane.

Still do not have <— Last few GCs —> / FATAL ERROR above the stack in the scrollback we captured — only the Stacktrace / JS stack then Illegal instruction. Happy to paste those lines if they show up on the next crash.

Host memory stays: 8192 MiB RAM + 512 MiB swap; cgroup memory.peak has been ~4.4 GiB.

Local workaround for postmortems (because the full V8 stack / FATAL dump only lived in terminal scrollback before): the same launcher wrapper now (1) tees agent stderr to ~/logs/cursor-agent/stderr/latest.log and (2) enables Node --report-on-fatalerror / --report-uncaught-exception into ~/logs/cursor-agent/reports/. That should catch Last few GCs / FATAL ERROR / Stacktrace on the next OOM even if the pane is gone. Hard SIGILL/SIGSEGV may still skip a report file; stderr tee is the backup.

Feature request: could cursor-agent / agent upstream do this by default (or behind a flag / env var) — persist full fatal stacktraces and Node diagnostic reports to a stable log directory on crash, instead of only printing them to the TTY? Happy to share the wrapper behavior if useful.

Great breakdown, and yeah, the missing NODE_OPTIONS in the pane is almost certainly why the first retest still crashed. The Herdr pane launcher doesn’t inherit your bashrc or environment.d, so until you added the V8 wrapper it was running with the default ceiling, about 2240 MiB on an 8 GiB CT. Wrapping agent or cursor-agent and launching it from a fresh pane is the right move, and a retest from there will be meaningful.

One note on memory to watch during the retest. On an 8 GiB container where cgroup memory.peak is already hitting about 4.4 GiB, and herdr.service in the same window is crashing with SIGBUS or SIGSEGV, the whole CT is close to the limit. Node heap 4096 MB plus herdr plus everything else has to fit into 8 GiB. If it doesn’t, the crash might be coming from the cgroup OOM killer or general memory pressure, not V8 itself, and raising --max-old-space-size won’t help. So:

  • If you can, increase the container RAM. That should also stop the herdr crashes.
  • Or keep the heap at a value that leaves headroom under the cgroup limit, and watch memory.peak relative to the limit.

Your setup with --report-on-fatalerror and --report-uncaught-exception plus tee-ing stderr is exactly what you want. When you catch the next crash, please share either the Node report file report.*.json, or the <--- Last few GCs ---> and FATAL ERROR: ... JavaScript heap out of memory lines from stderr. That will clearly separate the two cases:

  • V8 heap OOM, you’ll see FATAL ERROR ... heap out of memory before the trap, then fixing the heap ceiling helps.
  • cgroup OOM kill or container pressure, the process just gets killed without the JS fatal line, then the fix is more container RAM, not --max-old-space-size.

On the feature request, persisting the full fatal stack trace plus the Node diagnostic report to a stable directory, not only to TTY, makes sense. I can’t share a timeline, but it’s a solid idea, and your wrapper example shows what’s missing. Let me know how the retest goes from the wrapped pane.