Skip to content

Cron lane self-deadlock: isolated agentTurn jobs never execute with default maxConcurrentRuns #42579

@JorgeMenaDev

Description

@JorgeMenaDev

Summary

Isolated agentTurn cron jobs deadlock on the cron lane when cron.maxConcurrentRuns is 1 (the default). Sessions get created in sessions.json but the LLM call never fires — transcript files are 0 bytes/missing, and jobs always hit their timeout.

Version / OS

  • OpenClaw: 2026.3.8 (stable)
  • OS: macOS 15.6 (arm64)
  • Node: v24.13.0

Repro (minimal)

  1. cron.maxConcurrentRuns at default (1), or explicitly set to 1
  2. Create any isolated cron with payload.kind: "agentTurn":
    {
      "sessionTarget": "isolated",
      "payload": { "kind": "agentTurn", "message": "Reply: OK", "timeoutSeconds": 60 }
    }
  3. Trigger via openclaw cron run <jobId> or wait for schedule
  4. Observe:
    • Session entry created in sessions.json
    • Transcript .jsonl file missing or 0 bytes ❌
    • Job times out ❌
    • Gateway logs show lane wait exceeded: lane=cron waitedMs=32586 queueAhead=0

Root cause

The cron runner queues work on the cron lane. The isolated agent turn (runEmbeddedPiAgent) is also invoked with lane: "cron". With maxConcurrentRuns: 1:

  1. Cron runner takes slot 1 on the cron lane
  2. Embedded agent run queues behind it on the same lane
  3. Agent run cannot start — only 1 slot available
  4. Cron runner cannot finish — waiting for agent run
  5. Deadlock until timeout kills everything

Workaround

Set cron.maxConcurrentRuns: 2 and restart:

// ~/.openclaw/openclaw.json
{
  "cron": {
    "maxConcurrentRuns": 2
  }
}
openclaw gateway restart

After this, the same canary cron completes in 4.6 seconds.

Affects

  • All embedded providers tested: Anthropic (claude-opus-4-6, claude-sonnet-4-6), GLM (glm-4.7)
  • Multiple agents tested: custom agents + main agent
  • Sub-agents spawned from live chat sessions work perfectly (same models, same tasks)
  • Only cron-initiated isolated sessions are affected

Log snippet

[diagnostic] lane wait exceeded: lane=cron waitedMs=32586 queueAhead=0

Suggestion

The cron isolated agent runner should not enqueue the embedded run onto the same cron lane the cron service is executing on. Options:

  • Use a distinct lane name for the embedded run (e.g. cron-agent)
  • Avoid lane nesting entirely
  • Or at minimum, set the default maxConcurrentRuns to 2+ so the default config works out of the box

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions