Skip to content

fix(delivery-queue): enhance Telegram 'bot was kicked' error with helpful hints#29085

Closed
kevinWangSheng wants to merge 3 commits into
openclaw:mainfrom
kevinWangSheng:fix/systemd-system-service
Closed

fix(delivery-queue): enhance Telegram 'bot was kicked' error with helpful hints#29085
kevinWangSheng wants to merge 3 commits into
openclaw:mainfrom
kevinWangSheng:fix/systemd-system-service

Conversation

@kevinWangSheng

Copy link
Copy Markdown
Contributor

Summary

When a cron job is configured to deliver to a Telegram Forum topic that restricts posting (e.g. topic:1 / General), the bot receives a 403: Forbidden: bot was kicked from the supergroup chat error. This message is identical to the error when the bot is actually removed from the group, making root cause analysis extremely difficult.

Fix

This PR adds a helper function enhanceErrorMessageWithHint() that:

  1. Detects the 'bot was kicked' error pattern
  2. Checks if the target includes a forum topic (:topic: syntax) or has a threadId set
  3. If so, appends a helpful hint explaining that the error may indicate the topic restricts posting to admins only, not that the bot was removed from the group

Testing

  • Built successfully with `pnpm build"
  • The fix is applied in the delivery recovery path where permanent errors are handled

Closes #29048

Kevin Shenghui added 2 commits February 27, 2026 11:29
- Add support for parsing code/code_block tags in rich text posts
- Add support for parsing pre (preformatted text) tags with language
- Handle share_chat message type for forwarded/merged messages

Fixes: openclaw#28578
- Add resolveSystemdScope() to detect if service should run in user or system scope
- Update resolveSystemdUnitPathForName() to use /etc/systemd/system for system scope
- Add OPENCLAW_SYSTEMD_SCOPE env var to configure scope (default: user)

fix(delivery-queue): enhance Telegram 'bot was kicked' error with helpful hints

- Add enhanceErrorMessageWithHint() to provide context for forum topic errors
- The 'bot was kicked' error is misleading when posting to locked forum topics
- Now includes a hint explaining the topic may restrict posting to admins only

Closes openclaw#29048
Closes openclaw#29051
@openclaw-barnacle openclaw-barnacle Bot added gateway Gateway runtime channel: feishu Channel integration: feishu size: S labels Feb 27, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1c730dfec2

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread src/daemon/systemd.ts
Comment on lines +43 to +45
const scope = resolveSystemdScope(env);
if (scope === "system") {
return path.posix.join("/etc/systemd/system", `${name}.service`);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Use matching systemctl scope for system units

When resolveSystemdUnitPathForName switches to /etc/systemd/system for OPENCLAW_SYSTEMD_SCOPE=system, the rest of src/daemon/systemd.ts still hard-codes systemctl --user (for example in assertSystemdAvailable and the install/manage flows), so system-scoped units are written to the system unit directory but controlled through the user manager. systemctl --help explicitly distinguishes --system (“Connect to system manager”) from --user (“Connect to user service manager”), so this path produces unit-not-found/reload failures whenever system scope is selected.

Useful? React with 👍 / 👎.

@greptile-apps

greptile-apps Bot commented Feb 27, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR bundles three separate fixes into a single commit:

  • delivery-queue: Added enhanceErrorMessageWithHint() to provide context when Telegram returns "bot was kicked" errors for forum topics with restricted posting permissions
  • systemd: Added support for system-scope systemd services via OPENCLAW_SYSTEMD_SCOPE environment variable
  • feishu: Enhanced message parsing to handle code blocks (code, code_block, pre tags) and share_chat forwarded messages

The delivery-queue enhancement addresses issue #29048 by detecting when a delivery target includes a forum topic (:topic: syntax or threadId parameter) and appending a helpful hint explaining that the error may indicate posting restrictions rather than bot removal.

One logical issue found: the threadId validation incorrectly treats 0 as a valid thread ID, which could show the hint inappropriately.

Confidence Score: 4/5

  • This PR is mostly safe to merge with one minor logic bug
  • The changes are well-structured and address legitimate issues. The threadId validation bug is minor since threadId=0 is unlikely in practice, but should be fixed for correctness. All three fixes are independent and low-risk.
  • Pay close attention to src/infra/outbound/delivery-queue.ts:410-411 for the threadId validation logic

Last reviewed commit: 1c730df

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

3 files reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

Comment on lines +410 to +411
const hasTopic =
target.includes(":topic:") || (threadId !== undefined && threadId !== null && threadId !== "");

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

threadId=0 incorrectly treated as valid. 0 !== "" evaluates to true, causing the hint to appear even though 0 isn't a valid Telegram thread ID.

Suggested change
const hasTopic =
target.includes(":topic:") || (threadId !== undefined && threadId !== null && threadId !== "");
const hasTopic = target.includes(":topic:") || Boolean(threadId);
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/infra/outbound/delivery-queue.ts
Line: 410-411

Comment:
threadId=0 incorrectly treated as valid. `0 !== ""` evaluates to true, causing the hint to appear even though 0 isn't a valid Telegram thread ID.

```suggestion
  const hasTopic = target.includes(":topic:") || Boolean(threadId);
```

How can I resolve this? If you propose a fix, please make it concise.

When provider is 'local', doctor only checked local.modelPath for the
model file path. But users can also configure the model via the generic
'model' field (e.g., hf:ggml-org/embeddinggemma-300m-qat-q8_0).

This fix adds a hasModelAsLocalPath() function that checks if the model
field contains hf: or http(s): paths, which are valid for local provider.

Fixes openclaw#29099
@openclaw-barnacle openclaw-barnacle Bot added the commands Command implementations label Feb 27, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 416c88017a

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

// provider === "auto": check all providers in resolution order
if (hasLocalEmbeddings(resolved.local)) {
// Also check the model field for hf:/http(s): paths which work with local provider
if (hasLocalEmbeddings(resolved.local) || hasModelAsLocalPath(resolved.model)) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Don’t treat memorySearch.model as local readiness in auto mode

The new hasModelAsLocalPath(resolved.model) short-circuit in auto mode can suppress the doctor warning even when no embedding provider is actually usable. If provider: "auto", local.modelPath is unset, and model is set to an hf:/http string, this branch returns early, but runtime auto-selection does not use memorySearch.model for local readiness (it only checks local.modelPath before trying local embeddings), so the gateway can still run without any embedding provider while openclaw doctor reports no issue.

Useful? React with 👍 / 👎.

@openclaw-barnacle

Copy link
Copy Markdown

This pull request has been automatically marked as stale due to inactivity.
Please add updates or it will be closed.

@openclaw-barnacle openclaw-barnacle Bot added the stale Marked as stale due to inactivity label Mar 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

channel: feishu Channel integration: feishu commands Command implementations gateway Gateway runtime size: S stale Marked as stale due to inactivity

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(telegram): 403 'bot was kicked' error is misleading when posting to a locked forum topic

2 participants