openclaw - ✅(Solved) Fix bug: Synology Chat plugin fails to deliver replies when peer ID contains channel prefix (e.g. "synology-chat:4") [1 pull requests, 2 comments, 3 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#49989Fetched 2026-04-08 01:00:29
View on GitHub
Comments
2
Participants
3
Timeline
9
Reactions
0
Author
Timeline (top)
referenced ×4cross-referenced ×3commented ×2

When a Synology Chat DM session is created with dmScope: "per-channel-peer", the session's to field is set to the full peer string "synology-chat:4" rather than just the numeric user ID "4".

When the plugin attempts to send a reply, this value is passed to parseNumericUserId() in src/client.ts. parseInt("synology-chat:4", 10) returns NaN, so user_ids is never set in the payload. The Synology Chat API then returns:

{"error":{"code":800,"errors":"no target"},"success":false}

sendMessage returns false after 3 retries, sendText throws, and the reply is silently lost with no log output indicating a delivery failure.

Error Message

{"error":{"code":800,"errors":"no target"},"success":false}

  • The sendText failure is completely silent — no warn/error log is emitted when sendMessage returns false. Adding a log line there would help diagnose this in future.

Root Cause

When a Synology Chat DM session is created with dmScope: "per-channel-peer", the session's to field is set to the full peer string "synology-chat:4" rather than just the numeric user ID "4".

When the plugin attempts to send a reply, this value is passed to parseNumericUserId() in src/client.ts. parseInt("synology-chat:4", 10) returns NaN, so user_ids is never set in the payload. The Synology Chat API then returns:

{"error":{"code":800,"errors":"no target"},"success":false}

sendMessage returns false after 3 retries, sendText throws, and the reply is silently lost with no log output indicating a delivery failure.

Fix Action

Fixed

PR fix notes

PR #50109: fix(synology-chat): strip channel prefix from peer ID before numeric parse

Description (problem / solution / changelog)

Summary

  • Fixes #49989 — Synology Chat replies silently dropped because parseNumericUserId("synology-chat:4") returns NaN (channel prefix not stripped before parseInt)
  • Strips the <channel>: prefix in parseNumericUserId so peer IDs stored as "synology-chat:4" correctly resolve to numeric user IDs
  • Adds regression test confirming user_ids: [4] is set when userId is "synology-chat:4"

Test plan

  • All 12 existing client.test.ts tests pass
  • New regression test verifies channel-prefixed peer ID → user_ids:[4]
  • pnpm format clean
  • Manual: configure Synology Chat, send a message, verify reply targets the correct user

🤖 Generated with Claude Code

Changed files

  • extensions/synology-chat/src/client.test.ts (modified, +14/-0)
  • extensions/synology-chat/src/client.ts (modified, +18/-2)

Code Example

{"error":{"code":800,"errors":"no target"},"success":false}

---

function parseNumericUserId(userId?: string | number): number | undefined {
  if (userId === undefined) {
    return undefined;
  }
  // Strip channel prefix (e.g. "synology-chat:4" -> "4")
  const raw = typeof userId === "string" ? userId.replace(/^[^:]+:/, "") : userId;
  const numericId = typeof raw === "number" ? raw : parseInt(raw, 10);
  return Number.isNaN(numericId) ? undefined : numericId;
}
RAW_BUFFERClick to expand / collapse

Description

When a Synology Chat DM session is created with dmScope: "per-channel-peer", the session's to field is set to the full peer string "synology-chat:4" rather than just the numeric user ID "4".

When the plugin attempts to send a reply, this value is passed to parseNumericUserId() in src/client.ts. parseInt("synology-chat:4", 10) returns NaN, so user_ids is never set in the payload. The Synology Chat API then returns:

{"error":{"code":800,"errors":"no target"},"success":false}

sendMessage returns false after 3 retries, sendText throws, and the reply is silently lost with no log output indicating a delivery failure.

Steps to Reproduce

  1. Configure Synology Chat channel with dmPolicy: "open"
  2. Set session.dmScope: "per-channel-peer" (default for local onboarding)
  3. Send a message to the bot
  4. Agent generates a reply but it is never delivered to Synology Chat

Expected Behavior

Replies are delivered. The numeric user ID should be extracted from the peer string by stripping the channel prefix.

Proposed Fix

In extensions/synology-chat/src/client.ts, update parseNumericUserId to strip the channel prefix before parsing:

function parseNumericUserId(userId?: string | number): number | undefined {
  if (userId === undefined) {
    return undefined;
  }
  // Strip channel prefix (e.g. "synology-chat:4" -> "4")
  const raw = typeof userId === "string" ? userId.replace(/^[^:]+:/, "") : userId;
  const numericId = typeof raw === "number" ? raw : parseInt(raw, 10);
  return Number.isNaN(numericId) ? undefined : numericId;
}

Additional Notes

  • The sendText failure is completely silent — no warn/error log is emitted when sendMessage returns false. Adding a log line there would help diagnose this in future.
  • The fetchChatUsers auto-block issue (NAS blocking OpenClaw after repeated failed user_list calls during startup) is a secondary problem that compounds this — once auto-blocked, even a fixed parseNumericUserId would fail to resolve user IDs.

extent analysis

Fix Plan

To resolve the issue, update the parseNumericUserId function in extensions/synology-chat/src/client.ts to strip the channel prefix before parsing the user ID.

Updated Code:

function parseNumericUserId(userId?: string | number): number | undefined {
  if (userId === undefined) {
    return undefined;
  }
  // Strip channel prefix (e.g. "synology-chat:4" -> "4")
  const raw = typeof userId === "string" ? userId.replace(/^[^:]+:/, "") : userId;
  const numericId = typeof raw === "number" ? raw : parseInt(raw, 10);
  return Number.isNaN(numericId) ? undefined : numericId;
}

Additional Step: Add a log line in the sendText function to diagnose future failures:

if (!sendMessage()) {
  console.error("Failed to send message");
  throw new Error("Message delivery failed");
}

Verification

To verify the fix, follow these steps:

  • Configure the Synology Chat channel with dmPolicy: "open"
  • Set session.dmScope: "per-channel-peer"
  • Send a message to the bot
  • Verify that the reply is delivered to Synology Chat
  • Check the logs for any error messages

Extra Tips

  • Make sure to test the updated code thoroughly to ensure that it works as expected.
  • Consider adding additional logging to help diagnose any future issues with message delivery.

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…

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: Synology Chat plugin fails to deliver replies when peer ID contains channel prefix (e.g. "synology-chat:4") [1 pull requests, 2 comments, 3 participants]