Skip to content

sessionKey silently overrides sessionTarget=isolated, causing cron jobs to collide with WebUI dashboard sessions #86202

@ctbritt

Description

@ctbritt

Summary

When a cron job has both sessionTarget: "isolated" and an explicit sessionKey value, OpenClaw uses the sessionKey and ignores sessionTarget. There's no warning at creation, no indication in openclaw cron list, and no documentation I could find calling this out.

The practical result: cron jobs whose sessionKey happens to be a WebUI dashboard session key will run INTO that dashboard session every time they fire. Symptoms include WebUI session-state confusion mid-conversation, AbortError: CLI run aborted when the user tries to interact after a cron firing, and cron output interleaving with dashboard messages in the same transcript.

In my environment, I discovered 10 of 25 cron jobs had this collision, accumulated quietly over months. Every interval-based keepalive job was hijacking dashboard sessions on each firing.

Version

OpenClaw 2026.5.22 (a374c3a) — macOS, Homebrew install.

Reproduction

  1. Open the WebUI dashboard and start a chat session
  2. From within that session (or via openclaw cron add while the dashboard is the active session), create a cron job
  3. openclaw cron get <id> will show:
{
  "sessionTarget": "isolated",
  "sessionKey": "agent:main:dashboard:<active-session-uuid>",
  ...
}

Both fields are populated. sessionTarget: "isolated" is silently ignored; the cron fires into the dashboard session on each run.

Expected behavior

One of:

  1. sessionTarget: "isolated" should always create a fresh session and ignore any inherited sessionKey
  2. If both are set, surface a warning at job creation
  3. Reject job creation that combines sessionTarget: "isolated" with a non-isolated sessionKey as a configuration error

Currently neither happens. The override is silent and counterintuitive given the docs around sessionTarget.

Workaround

openclaw cron edit <full-uuid> --clear-session-key on every affected job. sessionTarget: "isolated" then took effect properly.

Related issues found while debugging

These compounded the difficulty of finding and fixing the primary bug:

A. openclaw cron rm <partial-uuid> silently fails to persist

$ openclaw cron rm abc12345
{ "ok": true, "removed": false }   # exit 0
$ openclaw cron get abc12345
GatewayClientRequestError: cron job not found: abc12345

Looks like a successful delete. But jobs.json still has the job. On gateway restart, the job comes back.

Only full UUIDs trigger an actual persisted delete (returns "removed": true). Partial-ID rm modifies in-memory state but doesn't write to disk.

This actively misled debugging — jobs thought to be deleted came back after a routine restart.

B. openclaw cron list doesn't show sessionKey

There's no sessionKey column in cron list output and no --show-session-key flag. To audit for collisions you have to either cron get each job individually or script against jobs.json directly. Both are nuisances that masked this issue.

Suggestion: add a column or a --columns sessionKey opt-in.

C. No openclaw cron edit --clear-model flag

To remove a redundant payload.model override (common doctor warning), you have to edit jobs.json by hand. --clear-session-key, --clear-tools, and --clear-agent all exist; --clear-model would complete the set.

D. Doctor warning for "cron model overrides" is too noisy

It warns about all jobs with payload.model set, but many overrides are deliberate (cheap models for keepalive, premium for analysis). The warning should probably distinguish:

  • "different from default" — likely intentional, no action needed
  • "same as default" — redundant, safe to clear

Currently it just counts both, which makes the warning hard to act on.

Suggested fix priority

  1. (HIGH) Document the intended behavior of sessionTarget vs sessionKey, and surface a warning when both are set (or make sessionTarget: "isolated" always win)
  2. (HIGH) Fix cron rm <partial-uuid> silent persistence failure
  3. (MEDIUM) Add sessionKey visibility to cron list
  4. (LOW) Add --clear-model to cron edit
  5. (LOW) Refine doctor's model-override warning

How I noticed

Tracing AbortError: CLI run aborted errors that appeared mid-conversation in the WebUI. Eventually traced through gateway logs, agent session files, and jobs.json to find that a 3-hour cron job shared its sessionKey with the active dashboard session. The cron ran, executed for 2 minutes, ended with NO_REPLY — and the next message sent in the WebUI hit the session in a mid-cron state and aborted.

Once the pattern was clear, grepping jobs.json for dashboard in sessionKey revealed 9 more jobs with the same trap.

Metadata

Metadata

Assignees

No one assigned

    Labels

    P1High-priority user-facing bug, regression, or broken workflow.clawsweeper:fix-shape-clearClawSweeper found a clear likely implementation shape for this issue.clawsweeper:queueable-fixClawSweeper marked this issue as an existing queue_fix_pr work candidate.clawsweeper:source-reproClawSweeper found a high-confidence source-level issue reproduction.impact:message-lossChannel message delivery can be lost, duplicated, or misrouted.impact:session-stateSession, memory, transcript, context, or agent state can drift or corrupt.issue-rating: 🦞 diamond lobsterVery strong issue quality with high-confidence source-level or clear reproduction.

    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