agent.service exits 1/FAILURE mid-PR-review with 3.1G memory peak #291
Labels
No labels
Agent
Compat/Breaking
Kind/Bug
Kind/Documentation
Kind/Enhancement
Kind/Feature
Kind/Security
Kind/Testing
Priority
Critical
Priority
High
Priority
Low
Priority
Medium
Reviewed
Confirmed
Reviewed
Duplicate
Reviewed
Invalid
Reviewed
Won't Fix
Status
Abandoned
Status
Blocked
Status
Need More Info
No milestone
No assignees
1 participant
Notifications
Total time spent: 1 minute 10 seconds
Due date
igor
1 minute 10 seconds
No due date set.
Dependencies
No dependencies set
Reference
joshtronic/igor#291
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
The 21:45 tick claimed PR review of
joshtronic/vps-showdown#22, invoked claude (30m timeout) at 21:46:00, ran ~11 minutes installing deps and running the repo's jest/lint/prettier suites inside the review worktree, then the unit exited nonzero before producing a verdict. Notable: memory peak was 3.1G (normal ticks ~13M; the earlier 21:44 review tick was 157.4M). The timeout was not reached, so the status=1 exit is unexplained. The review work was abandoned and re-started from scratch by the 21:58 tick (reopened + reassigned to bot), so no verdict was lost permanently, but the crash itself is a real fault and fits the "tick dies mid-call" pattern that commitfeat(crashlog): preserve the claude stream when a tick dies mid-call (observe #279)only instruments, not fixes.Fixed looks like: PR-review claude invocations complete with a logged verdict (or a clean handled timeout) without the unit exiting nonzero; investigate whether the 3.1G spike (npm install + jest run in-worktree) is hitting an OOM/resource ceiling that kills the run, and cap/contain it so a single PR review can't crash the tick.
service: agent.service
severity: medium
window: 2026-06-29 21:00-22:00 (filed by the hourly logwatch pass)
Re-scoped + root-caused → fix in #296
The OOM/memory framing in this ticket is wrong (worth recording): the box has 31G total / ~27G free, the service has no memory cap, and there were zero kernel OOM-kill events at either crash time (21:57 and the later 23:44 repeat). Both crashes exited
status=1, and one peaked at only 682M. So nothing hit a resource ceiling — the "3.1G peak" was incidental.Actual root cause (reproduced): an errexit leak in
claude_run_with_cost. It runs the stream pipeline underset +e, then restored errexit with an unconditionalset -ebefore its bookkeeping. Every caller wraps the call inset +eto capture a nonzero claude exit — but that internalset -eclobbers the guard, so when claude exits nonzero (a recoverable model crash mid-stream) the nonzeroreturntrips errexit in the caller and kills the tick before it reads$?. That is exactly the "status=1, noclaude exitedline" signature. Not Node-specific — heavy Node reworks just hit nonzero claude exits most often.Fix (#296): restore the caller's errexit instead of forcing
set -e; the bookkeeping is already|| true-guarded. Plusbin/test-claude-errexit.sh, which fails against the old code and passes against the fix.Status: #294 already handled the emergency (loop-break after 2 crashes + crashlog trap). #296 is the root-cause fix — once it merges, a recoverable model exit stays a handled outcome and the bot can rework Node-repo PRs instead of bouncing every one to you. This issue auto-closes when #296 merges.