openclaw - ✅(Solved) Fix [Bug]: cron with sessionTarget=current still lowercases Matrix roomId in 2026.4.27 (regression of #71798 via MCP loopback path) [1 pull requests, 1 comments, 2 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#75261Fetched 2026-05-01 05:36:06
View on GitHub
Comments
1
Participants
2
Timeline
2
Reactions
2
Author
Timeline (top)
commented ×1cross-referenced ×1

The fix from #71798 (commit e309fd485e, released in 2026.4.25) does not cover the case where mcp__openclaw__cron action=add with sessionTarget: "current" (and no explicit delivery) is invoked from a Claude CLI subprocess via the MCP loopback HTTP server. The created cron job still stores a lowercased Matrix room ID in delivery.to, causing the same M_UNKNOWN: non-create event for room of unknown version [500] error and infinite retry loop (deleteAfterRun: true never applies because runs always fail).

Reproduced on 2026.4.27 (latest stable, published 2026-04-29).

Error Message

2026-04-30T22:38:36 [agent/embedded] embedded run agent end: runId=553822d6-... isError=true model=claude-opus-4-7 provider=anthropic error=LLM request rejected: Third-party apps now draw from your extra usage, not your plan limits.

2026-04-30T... [cron] last error: M_UNKNOWN: MatrixError: [500] non-create event for room of unknown version in !c9p9xfwih5szl4yzip:matrix.devlabz.eu (https://matrix.devlabz.eu/_matrix/client/v3/rooms/%21c9p9xfwih5szl4yzip%3Amatrix.devlabz.eu/send/m.room.message/...)

jobs-state.json:

"state": { "lastRunStatus": "error", "lastStatus": "error", "consecutiveErrors": 3, "lastError": "M_UNKNOWN: MatrixError: [500] non-create event for room of unknown version in !c9p9xfwih5szl4yzip:matrix.devlabz.eu" }

Root Cause

The fix from #71798 (commit e309fd485e, released in 2026.4.25) does not cover the case where mcp__openclaw__cron action=add with sessionTarget: "current" (and no explicit delivery) is invoked from a Claude CLI subprocess via the MCP loopback HTTP server. The created cron job still stores a lowercased Matrix room ID in delivery.to, causing the same M_UNKNOWN: non-create event for room of unknown version [500] error and infinite retry loop (deleteAfterRun: true never applies because runs always fail).

Fix Action

Workaround

Force every cron creation that should deliver to a Matrix room to include delivery explicitly with the canonical-cased to:

{
  "delivery": {
    "mode": "announce",
    "channel": "matrix",
    "to": "!c9p9XFWiH5Szl4yZiP:matrix.devlabz.eu"
  }
}

Documented this as a hard rule in our agent's AGENTS.md so the LLM never relies on the implicit sessionTarget: "current" derivation for Matrix.

PR fix notes

PR #75303: fix(cron): preserve channel ID case in MCP loopback delivery context (#75261)

Description (problem / solution / changelog)

Summary

Fixes #75261 — cron jobs created via mcp__openclaw__cron action=add with sessionTarget=current from a Claude CLI subprocess (MCP loopback path) stored a lowercased Matrix room ID in delivery.to, causing M_UNKNOWN: non-create event for room of unknown version [500] on every cron run.

Root cause: The MCP loopback tool resolution path (resolveGatewayScopedTools called from McpLoopbackToolCache) had no currentChannelId. The cron tool fell back to inferDeliveryFromSessionKey, which passes the session key through parseAgentSessionKeynormalizeOptionalLowercaseString → lowercase.

The fix from #71798 (inferDeliveryFromContext) already preserves the channel ID correctly, but only activates when currentChannelId is populated. This PR threads the case-sensitive channel ID through the entire loopback pipeline:

  1. RunCliAgentParams.currentChannelId (new field)
  2. OPENCLAW_MCP_CURRENT_CHANNEL_ID env var → x-openclaw-current-channel-id header
  3. McpRequestContext.currentChannelId (parsed from header, not normalized to lowercase)
  4. McpLoopbackToolCache.resolveresolveGatewayScopedToolscreateOpenClawTools

Test plan

  • New regression test: x-openclaw-current-channel-id header with mixed-case Matrix room ID is passed unchanged to resolveGatewayScopedTools (currentChannelId: "!c9p9XFWiH5Szl4yZiP:matrix.example")
  • Existing createMcpLoopbackServerConfig test updated to assert the new header template is present
  • 60/60 mcp-http.test.ts tests pass; 1799/1799 gateway tests pass

🤖 Generated with Claude Code

Changed files

  • CHANGELOG.md (modified, +1/-0)
  • src/agents/cli-runner/prepare.ts (modified, +1/-0)
  • src/agents/cli-runner/types.ts (modified, +2/-0)
  • src/agents/command/attempt-execution.ts (modified, +1/-0)
  • src/gateway/mcp-http.loopback-runtime.ts (modified, +1/-0)
  • src/gateway/mcp-http.request.ts (modified, +3/-0)
  • src/gateway/mcp-http.runtime.ts (modified, +0/-0)
  • src/gateway/mcp-http.test.ts (modified, +33/-0)
  • src/gateway/mcp-http.ts (modified, +1/-0)
  • src/gateway/tool-resolution.ts (modified, +2/-0)

Code Example

{
  "name": "ping-salon-22h37",
  "agentId": "main",
  "sessionKey": "agent:main:matrix:channel:!c9p9xfwih5szl4yzip:matrix.devlabz.eu",
  "schedule": {"kind": "at", "at": "2026-04-30T20:37:00.000Z"},
  "sessionTarget": "session:agent:main:matrix:channel:!c9p9xfwih5szl4yzip:matrix.devlabz.eu",
  "deleteAfterRun": true,
  "delivery": {
    "mode": "announce",
    "to": "!c9p9xfwih5szl4yzip:matrix.devlabz.eu",
    "channel": "matrix"
  }
}

---

{
  "delivery": {
    "mode": "announce",
    "channel": "matrix",
    "to": "!c9p9XFWiH5Szl4yZiP:matrix.devlabz.eu"
  }
}

---

2026-04-30T22:38:36 [agent/embedded] embedded run agent end: runId=553822d6-... isError=true
  model=claude-opus-4-7 provider=anthropic
  error=LLM request rejected: Third-party apps now draw from your extra usage,
  not your plan limits.

2026-04-30T... [cron] last error:
  M_UNKNOWN: MatrixError: [500] non-create event for room of unknown version
  in !c9p9xfwih5szl4yzip:matrix.devlabz.eu
  (https://matrix.devlabz.eu/_matrix/client/v3/rooms/%21c9p9xfwih5szl4yzip%3Amatrix.devlabz.eu/send/m.room.message/...)

# jobs-state.json:
"state": {
  "lastRunStatus": "error",
  "lastStatus": "error",
  "consecutiveErrors": 3,
  "lastError": "M_UNKNOWN: MatrixError: [500] non-create event for room of unknown version in !c9p9xfwih5szl4yzip:matrix.devlabz.eu"
}
RAW_BUFFERClick to expand / collapse

Bug type

Behavior bug (incorrect output/state without crash)

Beta release blocker

No

Summary

The fix from #71798 (commit e309fd485e, released in 2026.4.25) does not cover the case where mcp__openclaw__cron action=add with sessionTarget: "current" (and no explicit delivery) is invoked from a Claude CLI subprocess via the MCP loopback HTTP server. The created cron job still stores a lowercased Matrix room ID in delivery.to, causing the same M_UNKNOWN: non-create event for room of unknown version [500] error and infinite retry loop (deleteAfterRun: true never applies because runs always fail).

Reproduced on 2026.4.27 (latest stable, published 2026-04-29).

Steps to reproduce

  1. Run OpenClaw 2026.4.27 with the Matrix channel enabled.
  2. Configure an agent (e.g. main) that uses claude-cli as backend (liveSession: claude-stdio), so it spawns a claude subprocess that talks to the MCP loopback over HTTP.
  3. From a Matrix room with uppercase characters in the room ID (e.g. !c9p9XFWiH5Szl4yZiP:matrix.example), ask the agent to schedule a one-shot reminder (mcp__openclaw__cron action=add, sessionTarget: "current", no delivery).
  4. Inspect ~/.openclaw/cron/jobs.json for the created job.
  5. Wait for the cron to fire.

Expected behavior

After fix #71798, currentDeliveryContext.to should preserve the case-sensitive Matrix room ID and the cron delivery.to should be the canonical-cased ID (e.g. !c9p9XFWiH5Szl4yZiP:...). The scheduled message delivers successfully and deleteAfterRun: true removes the job after one run.

Actual behavior

The created cron job stores lowercased sessionTarget and delivery.to:

{
  "name": "ping-salon-22h37",
  "agentId": "main",
  "sessionKey": "agent:main:matrix:channel:!c9p9xfwih5szl4yzip:matrix.devlabz.eu",
  "schedule": {"kind": "at", "at": "2026-04-30T20:37:00.000Z"},
  "sessionTarget": "session:agent:main:matrix:channel:!c9p9xfwih5szl4yzip:matrix.devlabz.eu",
  "deleteAfterRun": true,
  "delivery": {
    "mode": "announce",
    "to": "!c9p9xfwih5szl4yzip:matrix.devlabz.eu",
    "channel": "matrix"
  }
}

Each run errors with M_UNKNOWN: MatrixError: [500] non-create event for room of unknown version and the job retries indefinitely (3 errors observed in 5 minutes, backoff schedule 30s → 60s → 5min → 15min → 60min). Because the run is never lastRunStatus: "ok", deleteAfterRun: true never triggers.

Worse: each failed cron run takes the embedded code path which uses provider=anthropic directly (not claude-cli subprocess). Combined with Anthropic's recent third-party app billing rejection (HTTP 400 Third-party apps now draw from your extra usage), every retry pollutes logs with cascading fallback failures across anthropic/claude-opus-4-7 → anthropic/claude-sonnet-4-6 → anthropic/claude-opus-4-6 → ollama-cloud/....

Hypothesis on root cause

The fix in e309fd485e introduces inferDeliveryFromContext(opts.currentDeliveryContext) in createCronTool, with currentDeliveryContext.to sourced from options.currentChannelId ?? options.agentTo (line ~8880 in openclaw-tools-*.js). The non-embedded code path wires this correctly.

In our case (MCP loopback HTTP from a Claude CLI subprocess in claude-stdio live session mode):

  • The cron tool is reached via the loopback HTTP server, not the in-process createCronTool instance. The HTTP path may instantiate the cron tool through a different wiring that does not populate currentDeliveryContext, falling back to inferDeliveryFromSessionKey(agentSessionKey) which uses the lowercased parseAgentSessionKey output (session-key-utils-*.js normalizeOptionalLowercaseString).
  • Or currentChannelId itself is already lowercased in the request context before reaching the loopback handler (e.g. derived from originTo of a session whose store entry has lowercased channelId).

OpenClaw version

2026.4.27

Operating system

Linux 7.0.0-1-cachyos (Arch CachyOS)

Install method

Global npm install (npm install -g [email protected]), running as systemd user unit on edge node.

Model

claude-cli/claude-opus-4-7 (primary), with liveSession: claude-stdio (Claude CLI subprocess, MCP loopback HTTP)

Provider / routing chain

Matrix room → agent mainclaude-cli backend (subprocess) → MCP loopback HTTP → mcp__openclaw__cron

Workaround

Force every cron creation that should deliver to a Matrix room to include delivery explicitly with the canonical-cased to:

{
  "delivery": {
    "mode": "announce",
    "channel": "matrix",
    "to": "!c9p9XFWiH5Szl4yZiP:matrix.devlabz.eu"
  }
}

Documented this as a hard rule in our agent's AGENTS.md so the LLM never relies on the implicit sessionTarget: "current" derivation for Matrix.

Logs, screenshots, and evidence

2026-04-30T22:38:36 [agent/embedded] embedded run agent end: runId=553822d6-... isError=true
  model=claude-opus-4-7 provider=anthropic
  error=LLM request rejected: Third-party apps now draw from your extra usage,
  not your plan limits.

2026-04-30T... [cron] last error:
  M_UNKNOWN: MatrixError: [500] non-create event for room of unknown version
  in !c9p9xfwih5szl4yzip:matrix.devlabz.eu
  (https://matrix.devlabz.eu/_matrix/client/v3/rooms/%21c9p9xfwih5szl4yzip%3Amatrix.devlabz.eu/send/m.room.message/...)

# jobs-state.json:
"state": {
  "lastRunStatus": "error",
  "lastStatus": "error",
  "consecutiveErrors": 3,
  "lastError": "M_UNKNOWN: MatrixError: [500] non-create event for room of unknown version in !c9p9xfwih5szl4yzip:matrix.devlabz.eu"
}

Suggested fix direction

Either:

  1. Ensure currentDeliveryContext is populated in the MCP loopback HTTP path the same way it is for the in-process tool (line 8876 in bundled openclaw-tools), by reading the room ID from the session store (origin.nativeChannelId is preserved with correct casing in ~/.openclaw/agents/<id>/sessions/sessions.json), or
  2. In inferDeliveryFromSessionKey, instead of using the lowercased agentSessionKey, look up the canonical channel ID from the session store using the parsed agentId/rest tuple — Matrix room IDs (and other case-sensitive provider IDs) should be re-canonicalized from the store rather than reconstructed from a lowercased session key.

extent analysis

TL;DR

To fix the issue, ensure that currentDeliveryContext is populated correctly in the MCP loopback HTTP path or modify inferDeliveryFromSessionKey to re-canonicalize Matrix room IDs from the session store.

Guidance

  • Verify that the currentDeliveryContext is being populated as expected in the MCP loopback HTTP path by checking the code at line 8876 in openclaw-tools.
  • Consider modifying inferDeliveryFromSessionKey to look up the canonical channel ID from the session store instead of using the lowercased agentSessionKey.
  • Ensure that the session store (~/.openclaw/agents/<id>/sessions/sessions.json) contains the correct casing for the room ID in origin.nativeChannelId.
  • As a temporary workaround, include delivery explicitly with the canonical-cased to in every cron creation that should deliver to a Matrix room.

Example

No code example is provided as the issue is specific to the OpenClaw implementation and requires a detailed understanding of the codebase.

Notes

The suggested fix direction involves modifying the OpenClaw code to correctly handle case-sensitive Matrix room IDs. The exact implementation details may vary depending on the specific requirements and constraints of the project.

Recommendation

Apply the workaround of including delivery explicitly with the canonical-cased to in every cron creation that should deliver to a Matrix room, as this provides a reliable and immediate solution to the issue.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

FAQ

Expected behavior

After fix #71798, currentDeliveryContext.to should preserve the case-sensitive Matrix room ID and the cron delivery.to should be the canonical-cased ID (e.g. !c9p9XFWiH5Szl4yZiP:...). The scheduled message delivers successfully and deleteAfterRun: true removes the job after one run.

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

openclaw - ✅(Solved) Fix [Bug]: cron with sessionTarget=current still lowercases Matrix roomId in 2026.4.27 (regression of #71798 via MCP loopback path) [1 pull requests, 1 comments, 2 participants]