OpenClaw Zombie Sessions in sessions.json After Subagent Crash

Published April 17, 2026 · Bug #67902 · Affects: 2026.4.15 · Platform: All

You spawn a subagent. It crashes — maybe the host rebooted, maybe you sent a SIGKILL, maybe it just died. You restart your gateway and everything looks fine. But quietly, sessions.json has grown another stale ghost entry with status: "running" that will never go away on its own.

Over time, this file accumulates hundreds of zombie entries. External monitoring scripts that read it directly see agents that haven't existed for weeks. And the file keeps growing.

What's Happening

OpenClaw tracks active subagent sessions in two places:

  1. An in-memory registry — used by the subagents tool API
  2. ~/.openclaw/agents/main/sessions/sessions.json — the persistent file on disk

When a subagent exits cleanly, both get updated. When a subagent crashes (SIGKILL, host reboot, OOM kill), only the in-memory registry gets cleaned up on the next gateway start. The sessions.json entry is never touched — it stays status: "running" with the original startedAt timestamp, forever.

This creates a split-brain state: the subagents API shows nothing, but sessions.json shows it as actively running.

How to Tell If You Have Zombies

# Check for entries with status "running" that are old
cat ~/.openclaw/agents/main/sessions/sessions.json | \
  python3 -c "
import json, sys, datetime
data = json.load(sys.stdin)
now = datetime.datetime.utcnow()
for s in data.get('sessions', []):
    if s.get('status') == 'running':
        started = s.get('startedAt', '')
        print(f\"RUNNING: {s.get('id','?')} started={started}\")
"

If you see sessions marked running with timestamps from hours or days ago — those are zombies.

Manual Cleanup (The Current Workaround)

Until OpenClaw adds automatic TTL-based cleanup, you'll need to edit the file manually or use a script.

Option 1: Quick Manual Edit

# Back it up first
cp ~/.openclaw/agents/main/sessions/sessions.json \
   ~/.openclaw/agents/main/sessions/sessions.json.bak

# Open and remove stale "running" entries
nano ~/.openclaw/agents/main/sessions/sessions.json

Remove any entries where status is "running" and the startedAt timestamp is more than 30 minutes ago (and you know no subagent is actually running).

Option 2: Cleanup Script

Save this as cleanup-sessions.py and run it when needed (with the gateway stopped):

import json, os, datetime

path = os.path.expanduser(
    "~/.openclaw/agents/main/sessions/sessions.json"
)

with open(path) as f:
    data = json.load(f)

now = datetime.datetime.utcnow()
cutoff = 30 * 60  # 30 minutes in seconds

cleaned = []
removed = 0
for s in data.get("sessions", []):
    if s.get("status") == "running":
        started_str = s.get("startedAt", "")
        try:
            started = datetime.datetime.fromisoformat(
                started_str.replace("Z", "+00:00")
            ).replace(tzinfo=None)
            age = (now - started).total_seconds()
            if age > cutoff:
                print(f"Removing zombie: {s.get('id')} (age {age/60:.0f}m)")
                removed += 1
                continue
        except Exception:
            pass
    cleaned.append(s)

data["sessions"] = cleaned
with open(path, "w") as f:
    json.dump(data, f, indent=2)

print(f"Done. Removed {removed} zombie session(s).")
openclaw gateway stop
python3 cleanup-sessions.py
openclaw gateway start

Option 3: Cron-Based Maintenance

If you run long-lived gateways with lots of subagent activity, schedule the cleanup script daily:

# Add to crontab (runs at 3 AM daily)
0 3 * * * openclaw gateway stop && python3 ~/cleanup-sessions.py && openclaw gateway start

Impact on Your Setup

For most users with occasional subagent use, this is a minor annoyance. For power users running automated pipelines with dozens of subagents per day, sessions.json can grow to thousands of stale entries within weeks, and any external tooling that reads it directly will give garbage data.

When Will It Be Fixed?

The fix involves one of two approaches: process-exit hooks that update sessions.json on abnormal termination, or a startup reconciliation pass that marks stale running entries as crashed. Track progress at issue #67902.

Need Help?

If your OpenClaw setup is accumulating session cruft or you want a properly maintained multi-agent configuration, ClawReady can help you get it clean and keep it that way.

← Back to blog