Skip to content

[Bug]: Signal group auto-replies broken again in v2026.5.12 because Signal group IDs are lowercased #82827

@estdrzfgzhiutz4

Description

@estdrzfgzhiutz4

Bug type

Regression (worked before, now fails)

Beta release blocker

No

Summary

Signal group auto-replies are broken again in v2026.5.12.

This is the same class of bug that has already been reported multiple times: OpenClaw lowercases Signal group IDs even though Signal group IDs are Base64-like, opaque, and case-sensitive.

Manual Signal group sends work when the exact mixed-case group ID is used. The Signal daemon works. The account is in the group. The model generates an answer. The answer appears in the OpenClaw web UI. But the generated answer is not delivered back to Signal.

This worked in my previous container running v2026.4.23. It breaks in v2026.5.12.

How is this still happening? Every new update seems to break something that worked before. This lowercase bug class has apparently existed for months, has been reported multiple times, and still keeps coming back in new code paths. Signal group IDs are case-sensitive. Lowercasing them is data corruption.

Environment

  • OpenClaw version with regression: v2026.5.12
  • Previously working OpenClaw version: v2026.4.23
  • signal-cli version: 0.14.1
  • Node runtime: 24.14.0
  • Signal integration: bundled signal-cli daemon over HTTP JSON-RPC
  • Signal daemon command observed:
/home/node/.openclaw/tools/bin/signal-cli -a +<REDACTED_SIGNAL_ACCOUNT> daemon --http 127.0.0.1:8080 --no-receive-stdout

Signal daemon starts normally:

[signal] [default] starting provider (http://127.0.0.1:8080)
signal-cli: INFO  DaemonCommand - Starting daemon in single-account mode for +<REDACTED_SIGNAL_ACCOUNT>
signal-cli: INFO  HttpServerHandler - Started HTTP server on /127.0.0.1:8080

What works

Manual OpenClaw Signal group send works when using the exact mixed-case Signal group ID:

node dist/index.js message send \
  --channel signal \
  --account '+<REDACTED_SIGNAL_ACCOUNT>' \
  -t 'signal:group:<SIGNAL_GROUP_ID_MIXED_CASE_WITH_PADDING>' \
  -m 'manual test' \
  --verbose \
  --json

Direct signal-cli / JSON-RPC send also works when the exact mixed-case group ID is used.

So the Signal daemon, account, group membership, and target ID are not the issue.

What does not work

A Signal group message triggers the OpenClaw agent.

The agent/model generates a response.

The response appears in the OpenClaw web UI.

But the response is never delivered back to the Signal group.

So the failure is after generation, in the Signal auto-reply / session / routing / delivery path.

Evidence: OpenClaw corrupts the Signal group ID

The real group ID from signal-cli listGroups -d is mixed-case, for example:

<SIGNAL_GROUP_ID_MIXED_CASE_WITH_PADDING>

OpenClaw creates/stores a lowercased version:

<SIGNAL_GROUP_ID_LOWERCASED_BY_OPENCLAW>

Those are not the same ID.

Signal group IDs are case-sensitive. Lowercasing this value corrupts it.

Evidence from sessions.json

~/.openclaw/agents/main/sessions/sessions.json contains lowercased session keys like:

agent:main:signal:group:<SIGNAL_GROUP_ID_LOWERCASED_BY_OPENCLAW>

Inside the same session entry, some fields still preserve the correct mixed-case group target:

{
  "deliveryContext": {
    "channel": "signal",
    "to": "group:<SIGNAL_GROUP_ID_MIXED_CASE_WITH_PADDING>",
    "accountId": "default"
  },
  "lastChannel": "signal",
  "lastTo": "group:<SIGNAL_GROUP_ID_MIXED_CASE_WITH_PADDING>",
  "channel": "signal",
  "groupId": "<SIGNAL_GROUP_ID_LOWERCASED_BY_OPENCLAW>"
}

This is internally inconsistent:

  • deliveryContext.to has the correct mixed-case group target.
  • lastTo has the correct mixed-case group target.
  • But the session key and groupId are corrupted/lowercased.

This should never happen.

Code paths that appear to be involved

This is not one isolated .toLowerCase().

While debugging the built JS in /app/dist, multiple paths were found that lowercase session keys, route keys, or peer IDs that can contain Signal group IDs.

/app/dist/session-key-DFEyR49L.js

buildAgentPeerSessionKey() lowercased params.peerId:

const peerId = normalizeLowercaseStringOrEmpty(params.peerId) || "unknown";

For Signal groups, params.peerId is the Signal group ID. Lowercasing it corrupts it.

There was also a similar lowercasing path in buildGroupHistoryKey():

const peerId = normalizeLowercaseStringOrEmpty(params.peerId) || "unknown";

/app/dist/resolve-route-DQZZzDyD.js

The route builder lowercased the entire result of buildAgentSessionKey(...):

const sessionKey = normalizeLowercaseStringOrEmpty(buildAgentSessionKey(...));

This corrupts session keys containing signal:group:<Base64GroupId>.

/app/dist/session-BGECYHCy.js

Inbound session recording lowercased session keys:

const canonicalSessionKey = normalizeLowercaseStringOrEmpty(sessionKey);
const targetSessionKey = normalizeLowercaseStringOrEmpty(update.sessionKey);

/app/dist/session-key-CDZmhV4O.js

Explicit session key normalization lowercases the whole session key before plugin normalization can preserve the Signal group ID:

function normalizeExplicitSessionKey(sessionKey, ctx) {
  const normalized = normalizeLowercaseStringOrEmpty(sessionKey);
  ...
  if (typeof next === "string" && next.trim()) return normalizeLowercaseStringOrEmpty(next);
  return normalized;
}

For a session key like this:

agent:main:signal:group:<SIGNAL_GROUP_ID_MIXED_CASE_WITH_PADDING>

this is fatal.

Required fix

OpenClaw needs a central rule:

External provider IDs must be treated as opaque unless the specific provider/plugin says otherwise.

For Signal specifically:

  • Preserve case for channel === "signal" && peerKind === "group".
  • Preserve case for :signal:group: session keys.
  • Preserve case for group:<id> targets when channel/provider is Signal.
  • Do not pass already-lowercased Signal session keys into plugin-specific normalizers.
  • Apply plugin-specific normalization before global fallback normalization.
  • Do not lowercase groupId, peerId, route keys, group history keys, or delivery keys when they contain Signal group IDs.

Regression tests needed

Please add tests that fail if this:

<SIGNAL_GROUP_ID_MIXED_CASE_WITH_PADDING>

ever becomes this:

<SIGNAL_GROUP_ID_LOWERCASED_BY_OPENCLAW>

The test should cover:

  1. inbound Signal group event normalization
  2. route resolution
  3. session key creation
  4. explicit session key normalization
  5. session store persistence
  6. group history key generation
  7. delivery context generation
  8. outbound Signal reply
  9. delivery recovery
  10. cron/proactive delivery if it uses the same target/session code

Impact

Signal group automation is effectively broken.

The most confusing part is that the system appears to work halfway:

  • Signal inbound works.
  • The agent receives the message.
  • The model generates the answer.
  • The web UI shows the answer.
  • But Signal delivery silently does not happen.

That sends users debugging OpenRouter, browser auth, signal-cli, delivery queues, and sessions, when the underlying issue is simply that OpenClaw corrupted a case-sensitive Signal group ID.

This needs to be fixed properly and tested so it does not come back in the next update again.

Steps to reproduce

Steps to reproduce

  1. Set up OpenClaw v2026.5.12 with the Signal channel enabled.

  2. Use a Signal account that is a member of a Signal group whose group ID contains mixed-case Base64 characters.

    Example placeholder:

    <SIGNAL_GROUP_ID_MIXED_CASE_WITH_PADDING>
    
  3. Confirm the real group ID from signal-cli:

    /home/node/.openclaw/tools/bin/signal-cli \
      -a +<REDACTED_SIGNAL_ACCOUNT> \
      listGroups -d

    The returned group ID should preserve mixed case.

  4. Confirm manual delivery works with the exact mixed-case group ID:

    node dist/index.js message send \
      --channel signal \
      --account '+<REDACTED_SIGNAL_ACCOUNT>' \
      -t 'signal:group:<SIGNAL_GROUP_ID_MIXED_CASE_WITH_PADDING>' \
      -m 'manual delivery test' \
      --verbose \
      --json

    Expected result: the message is delivered to the Signal group.

  5. Send a normal message in that Signal group that should trigger the OpenClaw agent.

  6. Observe that OpenClaw receives the Signal message and generates an answer.

  7. Open the OpenClaw web UI and confirm that the generated answer appears there.

  8. Observe that the generated answer is not delivered back to the Signal group.

  9. Inspect the session store:

    grep -R "<SIGNAL_GROUP_ID_LOWERCASED_BY_OPENCLAW>" \
      /home/node/.openclaw/agents/main/sessions/sessions.json
  10. Observe that sessions.json contains a lowercased session key, for example:

agent:main:signal:group:<SIGNAL_GROUP_ID_LOWERCASED_BY_OPENCLAW>
  1. Compare that with the correct mixed-case group ID from signal-cli listGroups -d:
<SIGNAL_GROUP_ID_MIXED_CASE_WITH_PADDING>
  1. Observe that OpenClaw has corrupted the Signal group ID by lowercasing it.

  2. Restart the container / gateway:

docker restart <OPENCLAW_CONTAINER>
  1. Inspect sessions.json again.

  2. Observe that the lowercased Signal group session key is recreated / retained, even though the real Signal group ID is mixed-case and manual delivery only works with the exact mixed-case ID.

Expected result

OpenClaw should preserve the Signal group ID exactly as returned by signal-cli.

The auto-reply generated by the agent should be delivered back to the Signal group.

Actual result

OpenClaw receives the Signal message and generates the answer, but the generated answer is only visible in the OpenClaw web UI and is not delivered back to Signal.

The session/routing state contains a lowercased Signal group ID, which corrupts the case-sensitive Base64 group identifier.

Expected behavior

Signal group IDs must be treated as opaque, case-sensitive strings.

OpenClaw must never lowercase the Signal group ID portion of any of these:

signal:group:<id>
group:<id>
agent:<agent>:signal:group:<id>
deliveryContext.to
origin.from
origin.to
lastTo
groupId
session key peer id
group history key
route key
binding key
explicit session key

Lowercasing provider names, channel names, agent IDs, or enum-like values is fine.

Lowercasing the Signal group ID is not fine.

Actual behavior

OpenClaw lowercases Signal group IDs in one or more session/routing/delivery paths.

Manual group send works with the correct mixed-case group ID.

Auto-reply does not deliver, even though the web UI shows the generated answer.

Why this is serious

This is a regression from a working version.

The same setup works in v2026.4.23.

It breaks in v2026.5.12.

This bug class has reportedly been raised before. It should not keep returning in new paths after being “fixed” or closed. The root problem is treating opaque external IDs as lowercase-normalizable strings.

Please stop fixing this one .toLowerCase() at a time and fix the design centrally.

OpenClaw version

2026.5.12

Operating system

Debian GNU/Linux 12 (bookworm) docker container

Install method

docker

Model

all of them

Provider / routing chain

none

Additional provider/model setup details

No response

Logs, screenshots, and evidence

Impact and severity

Severity: High

This breaks Signal group automation in a way that is hard to diagnose.

The system appears to work at first:

  • Signal inbound messages are received.
  • The agent is triggered.
  • The model generates a response.
  • The response appears in the OpenClaw web UI.

But the generated response is not delivered back to the Signal group.

That makes the failure especially misleading, because users can waste time debugging the model provider, OpenRouter, browser/web UI state, signal-cli, authentication, delivery queues, and account registration, while the actual problem is that OpenClaw corrupted a case-sensitive Signal group ID by lowercasing it.

This is not cosmetic. It breaks a core channel integration.

For users relying on Signal group automation, the bot effectively stops working in groups after upgrading, even though the same setup worked in a previous version.

The impact is worse because:

  • Manual Signal group send works with the correct mixed-case group ID.
  • The Signal daemon and account are healthy.
  • The agent successfully generates the answer.
  • The failure happens only in the automatic reply/session/routing/delivery path.
  • There is no obvious user-facing error explaining that the group ID was corrupted.
  • Existing session state can contain lowercased/corrupted IDs.
  • The bug appears to have existed or reappeared across multiple code paths despite previous reports.

This should be treated as a regression and a release-blocking bug for Signal channel users, because it silently breaks a previously working integration after update.

Additional information

Version 2026.4.23 works.
But honestly, I am THIS close to giving up on that project. EVERY. SINGLE. UPDATE. breaks something absolutely basic.
Apparently this scope is not possible with AI or someone seriously doesn't care enough to think two steps ahead instead of just quick fixing everything.
Unrelated to this issue, but with the same update the whole container didnt start anymore because I had brave search in my config but not the plugin (it was built-in a few weeks ago), the WHOLE container didn't start anymore because no one thought about merging the old config to the new plugin system, really?

Metadata

Metadata

Assignees

No one assigned

    Labels

    P1High-priority user-facing bug, regression, or broken workflow.bugSomething isn't workingclawsweeper: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.regressionBehavior that previously worked and now fails

    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