Skip to content

fix: avoid ralph crash after a task is completed#256

Merged
frankbria merged 1 commit intofrankbria:mainfrom
haifengkao:FixRalphCrash
Apr 13, 2026
Merged

fix: avoid ralph crash after a task is completed#256
frankbria merged 1 commit intofrankbria:mainfrom
haifengkao:FixRalphCrash

Conversation

@haifengkao
Copy link
Copy Markdown
Contributor

@haifengkao haifengkao commented Apr 13, 2026

fix: extract result JSON from stream output regardless of SESSION_CONTINUITY

Problem

When SESSION_CONTINUITY=false and LIVE_OUTPUT=true (live mode), Ralph crashes silently during analyze_response after each successful Claude Code execution.

The loop ends at "Analyzing Claude Code response..." with no error output, and the Ralph process dies. Status JSON is never updated (stuck at "status": "running"), exit signals are never written, and Ralph never proceeds to the next loop.

Root Cause

In ralph_loop.sh line ~1602, the stream-json result extraction is guarded by:

if [[ "$CLAUDE_USE_CONTINUE" == "true" && -f "$output_file" ]]; then

When SESSION_CONTINUITY=false, this entire block is skipped. The block does two things:

  1. Extracts session_id for --continue (only needed when SESSION_CONTINUITY=true)
  2. Converts output_file from raw NDJSON to a single result JSON line (needed by analyze_response always)

Without the extraction, analyze_response receives the full multi-MB NDJSON stream (every stream_event, content_block_delta, etc.) instead of the clean {"type":"result", ...} object. This causes a silent crash during response parsing.

Reproduction

  1. Set SESSION_CONTINUITY=false in .ralphrc
  2. Run ralph --live --verbose
  3. Wait for Claude to complete a task successfully
  4. Observe: log ends at "Analyzing Claude Code response...", process dies, no _stream.log backup is created

Fix

Remove the CLAUDE_USE_CONTINUE guard so the result extraction always runs in live mode:

-        if [[ "$CLAUDE_USE_CONTINUE" == "true" && -f "$output_file" ]]; then
+        if [[ -f "$output_file" ]]; then

This is safe because:

  • The session_id that gets saved is harmless when SESSION_CONTINUITY=false — it's only read back when CLAUDE_USE_CONTINUE=true (line ~1456)
  • The _stream.log backup is useful for debugging regardless of session mode
  • analyze_response and save_claude_session both expect a single JSON object, not raw NDJSON (as noted in the code comment at line ~1616: "save_claude_session and analyze_response expect JSON format")

Impact

Without this fix, any user running SESSION_CONTINUITY=false with --live will have Ralph crash after every successful Claude execution. Ralph completes the task (commits are made, tests pass) but can never proceed to the next task or exit gracefully.

Ralph Log

---RALPH_STATUS---
   186   │ STATUS: BLOCKED
   187   │ TASKS_COMPLETED_THIS_SESSION: 0
   188   │ FILES_MOD
   189   │ [0m0;34m[2026-04-12 13:47:33] [INFO] Resuming Claude session: 160236a8-981b-4998-8... (0h old)
   190   │ [0m0;34m[2026-04-12 13:47:33] [INFO] Using modern CLI mode (json output)
   191   │ [0m0;34m[2026-04-12 13:47:33] [INFO] 📺 Live output mode enabled - showing Claude Code streaming...
   192   │ [0m0;34m[2026-04-12 13:47:44] [INFO] Extracted and validated session data from stream output
   193   │ [0m0;32m[2026-04-12 13:47:44] [SUCCESS] ✅ Claude Code execution completed successfully
   194   │ [0m0;34m[2026-04-12 13:47:44] [INFO] Saved Claude session: 160236a8-981b-4998-8...
   195   │ [0m0;34m[2026-04-12 13:47:44] [INFO] Tokens this hour: 1250/0 (+355)
   196   │ [0m0;34m[2026-04-12 13:47:44] [INFO] 🔍 Analyzing Claude Code response...
   197   │ [0m0;35m[2026-04-12 13:47:49] [LOOP] === Completed Loop #2 ===
   198   │ [0m0;34m[2026-04-12 13:47:49] [INFO] Loop #3 - calling init_call_tracking...
   199   │ [0m0;35m[2026-04-12 13:47:49] [LOOP] === Starting Loop #3 ===
   200   │ [2026-04-12 13:47:49] [DEBUG] Exit check: test_loops=0 done_signals=2 completion_indicators=2
   201   │ [0m1;33m[2026-04-12 13:47:49] [WARN] Exit condition: Multiple completion signals (2 >= 2)
   202   │ [0m0;32m[2026-04-12 13:47:49] [SUCCESS] 🏁 Graceful exit triggered: completion_signals
   203   │ [0m0;34m[2026-04-12 13:47:49] [INFO] Cleared exit signals file
   204   │ [0m0;34m[2026-04-12 13:47:49] [INFO] Session reset: project_complete
   205   │ [0m0;32m[2026-04-12 13:47:49] [SUCCESS] 🎉 Ralph has completed the project! Final stats:
   206   │ [0m0;34m[2026-04-12 13:47:49] [INFO]   - Total loops: 3
   207   │ [0m0;34m[2026-04-12 13:47:49] [INFO]   - API calls used: 11
   208   │ [0m0;34m[2026-04-12 13:47:49] [INFO]   - Exit reason: completion_signals
   209   │ [0m0;34m[2026-04-12 13:47:49] [INFO] Metrics summary: {
   210   │   "total_loops": 49,
   211   │   "successful": 36,
   212   │   "avg_duration": 1082.3469387755101,
   213   │   "total_calls": 49
   214   │ }
   215   │ [0m0;34m[2026-04-13 06:00:01] [INFO] Loaded configuration from .ralphrc
   216   │ [0m0;34m[2026-04-13 06:00:02] [INFO] Claude CLI version 2.1.104 (>= 2.0.76) - modern features enabled
   217   │ [0m0;34m[2026-04-13 06:00:02] [INFO] Could not check for Claude CLI updates (npm registry unreachable)
   218   │ [0m0;32m[2026-04-13 06:00:02] [SUCCESS] 🚀 Ralph loop starting with Claude Code
   219   │ [0m0;34m[2026-04-13 06:00:02] [INFO] Max calls per hour: 100
   220   │ [0m0;34m[2026-04-13 06:00:02] [INFO] Logs: .ralph/logs/ | Docs: .ralph/docs/generated/ | Status: .ralph/status.json
   221   │ [0m0;34m[2026-04-13 06:00:02] [INFO] Reset exit signals for fresh start
   222   │ [0m0;34m[2026-04-13 06:00:02] [INFO] Starting main loop...
   223   │ [0m0;34m[2026-04-13 06:00:02] [INFO] Loop #1 - calling init_call_tracking...
   224   │ [0m0;34m[2026-04-13 06:00:02] [INFO] Call and token counters reset for new hour: 2026041306
   225   │ [0m0;35m[2026-04-13 06:00:02] [LOOP] === Starting Loop #1 ===
   226   │ [2026-04-13 06:00:02] [DEBUG] Exit check: test_loops=0 done_signals=0 completion_indicators=0
   227   │ [0m0;35m[2026-04-13 06:00:02] [LOOP] Executing Claude Code (Call 1/100)
   228   │ [0m0;34m[2026-04-13 06:00:02] [INFO] ⏳ Starting Claude Code execution... (timeout: 120m)
   229   │ [0m0;34m[2026-04-13 06:00:02] [INFO] Loop context: Loop #1. Remaining tasks: 12.
   230   │ [0m0;34m[2026-04-13 06:00:02] [INFO] Using modern CLI mode (json output)
   231   │ [0m0;34m[2026-04-13 06:00:02] [INFO] 📺 Live output mode enabled - showing Claude Code streaming...
   232   │ [0m0;32m[2026-04-13 06:05:27] [SUCCESS] ✅ Claude Code execution completed successfully
   233   │ [0m0;34m[2026-04-13 06:05:27] [INFO] 🔍 Analyzing Claude Code response...

Summary by CodeRabbit

Bug Fixes

  • Improved session data handling in streaming mode to ensure session information is consistently extracted and processed whenever output data is available, enhancing session continuity reliability.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 13, 2026

Walkthrough

A condition in execute_claude_code() was modified to widen the session-continuity post-processing block, removing the CLAUDE_USE_CONTINUE check so that session data extraction runs whenever the stream output file exists, regardless of session continuity settings.

Changes

Cohort / File(s) Summary
Session-Continuity Logic
ralph_loop.sh
Relaxed the conditional gate on session-continuity post-processing by removing the CLAUDE_USE_CONTINUE flag requirement, allowing the script to parse and extract session data (result or system messages) from stream output unconditionally when the file is present.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~8 minutes

Possibly related PRs

Poem

🐰 A loop runs free, unguarded now,
Session streams flow without the vow,
No toggle needed, just the file—
Extraction happens all the while! ✨

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the main fix: preventing Ralph from crashing after task completion. It directly addresses the root cause and primary impact described in the PR objectives.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@ralph_loop.sh`:
- Around line 1599-1601: The existing comment block that begins with "# Extract
session ID from stream-json output for session continuity" is stale; update it
to state that this block always runs in live mode to normalize NDJSON for
downstream processing, that it still writes the full stream to _stream.log and
extracts the session_id from the final "result" message, and remove any wording
implying it is only for session continuity; ensure the new comment briefly
explains why normalization is needed and what outputs are produced (normalized
NDJSON and _stream.log) so future readers understand the current behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 1e96bf6a-eec6-4ef7-bc12-ea9277c0edae

📥 Commits

Reviewing files that changed from the base of the PR and between 2265569 and 4f3a86f.

📒 Files selected for processing (1)
  • ralph_loop.sh

Comment thread ralph_loop.sh
Comment on lines 1599 to 1601
# Extract session ID from stream-json output for session continuity
# Stream-json format has session_id in the final "result" type message
# Keep full stream output in _stream.log, extract session data separately
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Update stale comment to reflect new behavior.

The comment still frames this block as session-continuity-only, but it now always runs in live mode to normalize NDJSON for downstream processing.

✏️ Suggested comment update
-        # Extract session ID from stream-json output for session continuity
-        # Stream-json format has session_id in the final "result" type message
-        # Keep full stream output in _stream.log, extract session data separately
+        # Normalize stream-json NDJSON into a single result JSON object for downstream analysis
+        # and keep the full stream in _stream.log for debugging/session fallback.
+        # Session ID is extracted from result, with system-message fallback on truncation.

As per coding guidelines, "Update inline comments in bash scripts immediately when implementation changes, remove outdated comments".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ralph_loop.sh` around lines 1599 - 1601, The existing comment block that
begins with "# Extract session ID from stream-json output for session
continuity" is stale; update it to state that this block always runs in live
mode to normalize NDJSON for downstream processing, that it still writes the
full stream to _stream.log and extracts the session_id from the final "result"
message, and remove any wording implying it is only for session continuity;
ensure the new comment briefly explains why normalization is needed and what
outputs are produced (normalized NDJSON and _stream.log) so future readers
understand the current behavior.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants