Skip to content

Feature/telegram error policy#34498

Closed
chinar-amrutkar wants to merge 13 commits into
openclaw:mainfrom
chinar-amrutkar:feature/telegram-error-policy
Closed

Feature/telegram error policy#34498
chinar-amrutkar wants to merge 13 commits into
openclaw:mainfrom
chinar-amrutkar:feature/telegram-error-policy

Conversation

@chinar-amrutkar

@chinar-amrutkar chinar-amrutkar commented Mar 4, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Problem: When OpenClaw hits provider/rate limits, it can post the same error response repeatedly in active group chats
  • Why it matters: Creates spam, degrades trust, disrupts conversation flow in groups
  • What changed: Added errorPolicy (always|once|silent) and errorCooldownMs config at group/direct/topic/account levels
  • What did NOT change: Error handling in DMs (still sends all errors), core reply logic unchanged

Change Type

  • Bug fix
  • Feature

Scope

  • Gateway / orchestration
  • Integrations

Linked Issue/PR

User-visible / Behavior Changes

  • New config: channels.telegram.errorPolicy (always/once/silent)
  • New config: channels.telegram.errorCooldownMs (default: 4 hours)
  • New config: channels.telegram.groups.<groupId>.errorPolicy (per-group override)
  • Default behavior unchanged (errorPolicy defaults to "always")

Security Impact (required)

  • New permissions/capabilities? No
  • Secrets/tokens handling changed? No
  • New/changed network calls? No
  • Command/tool execution surface changed? No
  • Data access scope changed? No

Repro + Verification

Environment

  • OS: Linux
  • Runtime/container: OpenClaw gateway
  • Integration/channel: Telegram

Steps

  1. Configure errorPolicy: "once" in telegram channel config
  2. Trigger rate limit error
  3. Send another message to trigger same error

Expected

  • First error is shown
  • Subsequent errors during cooldown are suppressed

Actual

  • Behavior verified in code flow (in-memory cooldown tracking)

Evidence

  • Trace/log snippets - code implements cooldown tracking in error-policy.ts
  • Code changes - see diff

Human Verification (required)

  • Verified scenarios: Code compiles, logic correctly gates error display based on policy
  • Edge cases checked: Group config takes precedence over channel config, "silent" policy suppresses all errors
  • What you did not verify: Full E2E testing with live Telegram bot

Compatibility / Migration

  • Backward compatible? Yes (default is "always" which is current behavior)
  • Config/env changes? Yes (new optional config keys)
  • Migration needed? No

Failure Recovery (if this breaks)

  • How to disable/revert this change quickly: Set errorPolicy: "always" or remove config
  • Files/config to restore: src/config/zod-schema.providers-core.ts, src/telegram/bot-message-dispatch.ts, src/telegram/error-policy.ts
  • Known bad symptoms: If errorPolicy not set, defaults to "always" (current behavior)

Risks and Mitigations

  • Risk: In-memory cooldown store resets on gateway restart
    • Mitigation: Expected behavior; user can trigger fresh error after restart
  • Risk: Errors from different sources may have different error messages
    • Mitigation: Cooldown is time-based, not message-based

…sages

## Summary

- Problem: When OpenClaw hits provider/rate limits, it can post the same error response repeatedly in active group chats
- Why it matters: Creates spam, degrades trust, disrupts conversation flow in groups
- What changed: Added errorPolicy (always|once|silent) and errorCooldownMs config at group/direct/topic/account levels
- What did NOT change: Error handling in DMs (still sends all errors), core reply logic unchanged

## Change Type
- [x] Feature

## Scope
- [x] Integrations (Telegram channel)

## Linked Issue/PR
- Related openclaw#34114

## User-visible / Behavior Changes
- New config: channels.telegram.errorPolicy (always/once/silent)
- New config: channels.telegram.errorCooldownMs (default: 4 hours)
- New config: channels.telegram.groups.<groupId>.errorPolicy (per-group override)

## Security Impact
- New permissions/capabilities? No
- Secrets/tokens handling changed? No
- New/changed network calls? No
- Command/tool execution surface changed? No
- Data access scope changed? No

## Repro + Verification

### Environment
- OS: Linux
- Integration/channel: Telegram

### Steps
1. Configure errorPolicy: "once" in telegram channel config
2. Trigger rate limit error
3. Send another message to trigger same error

### Expected
- First error is shown
- Subsequent errors during cooldown are suppressed

### Actual
- Behavior verified in code flow (in-memory cooldown tracking)

## Evidence
- [x] Code changes implement the policy logic

## Human Verification
- Verified scenarios: Code compiles, logic correctly gates error display
- Edge cases checked: Group config takes precedence over channel config
- What you did not verify: Full E2E testing with live Telegram bot

## Compatibility / Migration
- Backward compatible? Yes (default is "always" which is current behavior)
- Config/env changes? Yes (new optional config)
- Migration needed? No

## Failure Recovery
- How to disable/revert: Set errorPolicy: "always" or remove config
- Files/config to restore: src/config/zod-schema.providers-core.ts, src/telegram/bot-message-dispatch.ts, src/telegram/error-policy.ts
- Known bad symptoms: If errorPolicy not set, defaults to "always" (current behavior)

## Risks and Mitigations
- Risk: In-memory cooldown store resets on restart
  - Mitigation: Expected for this feature; user can trigger fresh error after restart

AI-assisted (light testing)
@openclaw-barnacle openclaw-barnacle Bot added channel: telegram Channel integration: telegram size: S labels Mar 4, 2026
@greptile-apps

greptile-apps Bot commented Mar 4, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR introduces a configurable error-suppression policy (always / once / silent) and an errorCooldownMs setting for Telegram channels, intended to prevent repeated error messages from spamming group chats during rate-limit events. The schema changes are clean and backward-compatible, but there is a critical logic bug in the dispatch layer and two dead-code/dead-configuration issues in the new error-policy.ts module.

Key findings:

  • Critical logic bug (bot-message-dispatch.ts line 630): shouldSuppressTelegramError is called for every non-silent policy, including "always". This means the second error from the same chat within the cooldown window is suppressed even when the policy is "always" — the exact opposite of the intended behavior. The fix requires guarding the call with errorPolicy.policy === "once".
  • Dead parameter (error-policy.ts): accountId is included in the resolveTelegramErrorPolicy signature and destructured, but is never referenced. If per-account resolution is intended for multi-account setups it needs to be implemented; otherwise the parameter should be removed.
  • Dead configuration (error-policy.ts / zod-schema.providers-core.ts): TelegramTopicSchema now accepts errorPolicy, and the PR description explicitly lists topics as a supported config level, but resolveTelegramErrorPolicy never reads topic-level config. Users who configure a per-topic policy will see no effect.

Confidence Score: 2/5

  • Not safe to merge — the "always" error policy actively suppresses errors it should display, breaking the default-equivalent behavior for users who explicitly choose "always".
  • The critical bug in bot-message-dispatch.ts inverts the semantics of the "always" policy: after the first error in any chat, subsequent errors are silently swallowed during the cooldown window regardless of policy setting. This is a functional regression for any user who sets errorPolicy: "always" or relies on default error visibility. Additionally, topic-level policy config is dead code and the unused accountId parameter signals incomplete implementation.
  • src/telegram/bot-message-dispatch.ts (critical bug in onError handler) and src/telegram/error-policy.ts (unused parameter, missing topic resolution).

Last reviewed commit: 313ee36

Comment thread src/telegram/bot-message-dispatch.ts Outdated
Comment on lines +630 to +635
if (shouldSuppressTelegramError({
chatId,
cooldownMs: errorPolicy.cooldownMs,
errorMessage: String(err),
})) {
return;

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.

"always" policy incorrectly suppresses errors

shouldSuppressTelegramError is called unconditionally for both "always" and "once" policies (only "silent" is filtered out before this). On the second error from the same chat within the cooldown window, shouldSuppressTelegramError returns true and the error is swallowed — even when errorPolicy.policy === "always". This directly contradicts the semantics of the "always" policy.

The call must be guarded to only run for the "once" policy:

Suggested change
if (shouldSuppressTelegramError({
chatId,
cooldownMs: errorPolicy.cooldownMs,
errorMessage: String(err),
})) {
return;
if (errorPolicy.policy === "once" && shouldSuppressTelegramError({
chatId,
cooldownMs: errorPolicy.cooldownMs,
errorMessage: String(err),
})) {
return;
}
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/telegram/bot-message-dispatch.ts
Line: 630-635

Comment:
**"always" policy incorrectly suppresses errors**

`shouldSuppressTelegramError` is called unconditionally for both `"always"` and `"once"` policies (only `"silent"` is filtered out before this). On the second error from the same chat within the cooldown window, `shouldSuppressTelegramError` returns `true` and the error is swallowed — even when `errorPolicy.policy === "always"`. This directly contradicts the semantics of the `"always"` policy.

The call must be guarded to only run for the `"once"` policy:

```suggestion
          if (errorPolicy.policy === "once" && shouldSuppressTelegramError({
            chatId,
            cooldownMs: errorPolicy.cooldownMs,
            errorMessage: String(err),
          })) {
            return;
          }
```

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

Comment on lines +30 to +40
export function resolveTelegramErrorPolicy(params: {
cfg: OpenClawConfig;
channel: ChannelId;
accountId?: string | null;
chatId?: string | number | null;
isGroup?: boolean;
}): {
policy: TelegramErrorPolicy;
cooldownMs: number;
} {
const { cfg, channel, accountId, chatId, isGroup = false } = params;

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.

accountId parameter is accepted but never used

accountId is part of the function signature and is destructured on line 40, but it is never referenced in the function body. If the intent is to support per-account error policy overrides (e.g. when multiple Telegram accounts are configured under the same channel key), this is currently a no-op and the parameter is misleading. If per-account resolution is out of scope, the parameter should be removed to avoid confusion.

Suggested change
export function resolveTelegramErrorPolicy(params: {
cfg: OpenClawConfig;
channel: ChannelId;
accountId?: string | null;
chatId?: string | number | null;
isGroup?: boolean;
}): {
policy: TelegramErrorPolicy;
cooldownMs: number;
} {
const { cfg, channel, accountId, chatId, isGroup = false } = params;
export function resolveTelegramErrorPolicy(params: {
cfg: OpenClawConfig;
channel: ChannelId;
chatId?: string | number | null;
isGroup?: boolean;
}): {
policy: TelegramErrorPolicy;
cooldownMs: number;
} {
const { cfg, channel, chatId, isGroup = false } = params;
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/telegram/error-policy.ts
Line: 30-40

Comment:
**`accountId` parameter is accepted but never used**

`accountId` is part of the function signature and is destructured on line 40, but it is never referenced in the function body. If the intent is to support per-account error policy overrides (e.g. when multiple Telegram accounts are configured under the same channel key), this is currently a no-op and the parameter is misleading. If per-account resolution is out of scope, the parameter should be removed to avoid confusion.

```suggestion
export function resolveTelegramErrorPolicy(params: {
  cfg: OpenClawConfig;
  channel: ChannelId;
  chatId?: string | number | null;
  isGroup?: boolean;
}): {
  policy: TelegramErrorPolicy;
  cooldownMs: number;
} {
  const { cfg, channel, chatId, isGroup = false } = params;
```

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

Comment thread src/telegram/error-policy.ts Outdated
Comment on lines +48 to +58
// Check group-specific config first (if in a group and chatId is available)
if (isGroup && chatId) {
const chatIdStr = String(chatId);
const groupConfig = channelConfig.groups?.[chatIdStr];
if (groupConfig?.errorPolicy) {
return {
policy: groupConfig.errorPolicy,
cooldownMs: groupConfig.errorCooldownMs ?? DEFAULT_ERROR_COOLDOWN_MS,
};
}
}

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.

Topic-level errorPolicy configured in schema is never consulted

TelegramTopicSchema in zod-schema.providers-core.ts gains an errorPolicy field (and the PR description explicitly lists "topic" as a supported level), but resolveTelegramErrorPolicy only checks group-level and channel-level config. Any value a user sets under channels.telegram.groups.<groupId>.topics.<topicId>.errorPolicy is silently ignored.

Either the resolution logic here needs a topic-aware path (requiring a topicId parameter), or the errorPolicy field should be removed from TelegramTopicSchema to avoid a dead configuration key that creates a false expectation for users.

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/telegram/error-policy.ts
Line: 48-58

Comment:
**Topic-level `errorPolicy` configured in schema is never consulted**

`TelegramTopicSchema` in `zod-schema.providers-core.ts` gains an `errorPolicy` field (and the PR description explicitly lists "topic" as a supported level), but `resolveTelegramErrorPolicy` only checks group-level and channel-level config. Any value a user sets under `channels.telegram.groups.<groupId>.topics.<topicId>.errorPolicy` is silently ignored.

Either the resolution logic here needs a topic-aware path (requiring a `topicId` parameter), or the `errorPolicy` field should be removed from `TelegramTopicSchema` to avoid a dead configuration key that creates a false expectation for users.

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

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 313ee36b66

ℹ️ 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/telegram/bot-message-dispatch.ts Outdated
Comment on lines +630 to +634
if (shouldSuppressTelegramError({
chatId,
cooldownMs: errorPolicy.cooldownMs,
errorMessage: String(err),
})) {

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.

P1 Badge Skip cooldown suppression when policy is "always"

This suppression check runs for every non-silent policy, so the default errorPolicy: "always" still enters cooldown: after the first failure in a chat, subsequent failures inside errorCooldownMs return early and never reach markNonSilentFailure(). In practice, repeated provider/rate-limit failures stop producing fallback error responses, which is a behavior change from the previous "always report" default.

Useful? React with 👍 / 👎.

Comment thread src/telegram/error-policy.ts Outdated
} {
const { cfg, channel, accountId, chatId, isGroup = false } = params;

const channelConfig = cfg.channels?.[channel] as TelegramAccountConfig | undefined;

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.

P2 Badge Resolve error policy from the selected Telegram account

The resolver receives accountId but does not use it, and instead reads only cfg.channels[channel]; this means channels.telegram.accounts.<id>.errorPolicy/errorCooldownMs (and that account's group overrides) are ignored in multi-account deployments. The dispatcher passes route.accountId, but account-specific policy cannot take effect with the current lookup.

Useful? React with 👍 / 👎.

// Check group-specific config first (if in a group and chatId is available)
if (isGroup && chatId) {
const chatIdStr = String(chatId);
const groupConfig = channelConfig.groups?.[chatIdStr];

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.

P2 Badge Honor wildcard group error-policy overrides

Group policy lookup only checks the exact chat id and never falls back to groups["*"], so a global group override for errorPolicy/errorCooldownMs will be silently ignored. Telegram group config elsewhere already supports wildcard fallback, so this inconsistency will surprise operators who configure catch-all group behavior.

Useful? React with 👍 / 👎.

Use the accountId parameter to check account-level config first, then
group-level config within the account, before falling back to channel-level.

This addresses the PR review comment about accountId being unused.

AI-assisted

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6339b5d40c

ℹ️ 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 on lines +61 to +63
if (isGroup && chatId) {
const chatIdStr = String(chatId);
const groupConfig = accountConfig.groups?.[chatIdStr];

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.

P1 Badge Resolve DM/topic-specific error policy overrides

resolveTelegramErrorPolicy only performs per-chat lookups inside the isGroup branch and never evaluates direct or topic-level settings, so configs like channels.telegram.direct.<id>.errorPolicy and ...topics.<id>.errorPolicy are accepted by schema but have no runtime effect. This means operators cannot actually enable silent/once behavior for DMs or per-topic threads even though those keys were introduced in this change.

Useful? React with 👍 / 👎.

Comment on lines +64 to +68
if (groupConfig?.errorPolicy) {
return {
policy: groupConfig.errorPolicy,
cooldownMs: groupConfig.errorCooldownMs ?? DEFAULT_ERROR_COOLDOWN_MS,
};

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.

P2 Badge Allow cooldown overrides without redefining policy

The resolver only returns group/account overrides when errorPolicy is present, so errorCooldownMs is ignored if it is configured alone. In practice, if a channel-level policy is already set (for example once), setting only groups.<id>.errorCooldownMs or accounts.<id>.errorCooldownMs does nothing, which silently breaks cooldown-only overrides and forces redundant policy duplication.

Useful? React with 👍 / 👎.

errorMessage?: string;
}): boolean {
const { chatId, cooldownMs, errorMessage } = params;
const chatIdStr = String(chatId);

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.

P2 Badge Scope cooldown tracking key by account identity

Cooldown entries are keyed only by chatId, so failures from one Telegram account suppress error reporting for any other account that serves the same chat ID during the cooldown window. This creates cross-account interference in multi-account deployments (e.g., two bots in one group), where one route's failure state incorrectly affects another route's visibility.

Useful? React with 👍 / 👎.

Use Omit to properly type the channel config that includes
accounts map, matching TelegramConfigSchema structure.

AI-assisted
@chinar-amrutkar

Copy link
Copy Markdown
Contributor Author

Updated code based on the Greptile review.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 655bd28f18

ℹ️ 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 on lines +627 to +628
if (isSilentErrorPolicy(errorPolicy.policy)) {
return;

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.

P2 Badge Preserve runtime logging for silent error policy

Returning immediately for silent skips runtime.error?.(...), and this callback is the only place delivery exceptions are logged in this dispatch path. In chats configured as silent, transport/provider failures therefore disappear from operator logs entirely, which makes production outages hard to detect and diagnose even though only user-facing error messages were meant to be suppressed.

Useful? React with 👍 / 👎.

Comment on lines +123 to +125
if (now - entry.lastErrorTime < cooldownMs) {
// Within cooldown - suppress this error
return true;

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.

P2 Badge Differentiate cooldown suppression by error message

shouldSuppressTelegramError suppresses all failures during the cooldown window using only lastErrorTime, so a later unrelated failure in the same chat is dropped after any first error. This means a transient first error can mask a new incident (for example, an auth/config break) for up to errorCooldownMs, despite the function already receiving and storing errorMessage.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c46da932e5

ℹ️ 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".

// Check per-account config first (when accountId is provided)
const normalizedAccountId = accountId ?? null;
if (normalizedAccountId) {
const accountConfig = channelConfig.accounts?.[normalizedAccountId];

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.

P2 Badge Look up account overrides case-insensitively

resolveTelegramErrorPolicy fetches account overrides with a direct key lookup (channelConfig.accounts?.[normalizedAccountId]), but Telegram account IDs are resolved case-insensitively elsewhere (via resolveAccountEntry in account routing). If a config uses mixed-case account keys and runtime routing passes a normalized lowercase ID, account-level errorPolicy/errorCooldownMs are silently ignored and channel defaults are used instead.

Useful? React with 👍 / 👎.

Comment on lines +67 to +70
return {
policy: groupConfig.errorPolicy,
cooldownMs: groupConfig.errorCooldownMs ?? DEFAULT_ERROR_COOLDOWN_MS,
};

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.

P2 Badge Cascade cooldown from parent scopes before defaulting

When a scoped override sets errorPolicy but omits errorCooldownMs, the resolver immediately falls back to DEFAULT_ERROR_COOLDOWN_MS instead of inheriting a configured parent cooldown (account or channel). This means a global channels.telegram.errorCooldownMs is unexpectedly bypassed as soon as a group/account policy is customized, producing a 4-hour cooldown even when operators configured a different base cooldown.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a1eb8eb8d9

ℹ️ 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 on lines +113 to +118
if (!entry) {
// First error - record it and don't suppress
errorCooldownStore.set(chatIdStr, {
lastErrorTime: now,
errorMessage,
});

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.

P2 Badge Evict stale Telegram error cooldown entries

Each first delivery failure adds a chatId entry to the process-wide errorCooldownStore, but there is no code path that ever deletes entries after their cooldown window; later calls only overwrite timestamps for the same key. In long-lived gateways that see one-off errors across many chats, this map grows monotonically for the lifetime of the process and can become an avoidable memory leak.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1ff756ef19

ℹ️ 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 on lines +83 to +86
// Check group-specific config at channel level (for default account)
if (isGroup && chatId) {
const chatIdStr = String(chatId);
const groupConfig = channelConfig.groups?.[chatIdStr];

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.

P2 Badge Skip channel group fallback for named accounts

This fallback applies channels.telegram.groups for every account, not just the default account. In multi-account setups, mergeTelegramAccountConfig intentionally does not inherit channel-level groups into named accounts, but this code bypasses that rule and can make one account's group errorPolicy/errorCooldownMs suppress errors for another account in the same chat. That creates cross-account policy bleed and unexpected silent behavior in shared groups.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9f2269f1bb

ℹ️ 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".

errorMessage?: string;
}): boolean {
const { chatId, cooldownMs, errorMessage } = params;
const chatIdStr = String(chatId);

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.

P2 Badge Key Telegram cooldown suppression by thread id

shouldSuppressTelegramError uses only chatId as the cooldown key, so all forum topics (and DM topics) inside the same Telegram chat share one suppression window. With errorPolicy: "once", a transient failure in topic A will suppress subsequent failures in topic B until cooldown expires, which hides independent delivery incidents across threads that are otherwise routed separately in Telegram.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 11a9c08f87

ℹ️ 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 on lines +33 to +37
import {
isSilentErrorPolicy,
resolveTelegramErrorPolicy,
shouldSuppressTelegramError,
} from "./error-policy.js";

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.

P1 Badge Restore exec-approval helper import

This import block drops shouldSuppressLocalTelegramExecApprovalPrompt, but the dispatcher still calls that symbol in the delivery path; when a reply payload is handled, the missing binding causes a ReferenceError and aborts Telegram dispatch before sending the message. Because this is in the hot path for normal replies, it can break delivery broadly whenever this module runs without a strict type-check gate.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9b4bca48d1

ℹ️ 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 on lines 660 to +663
onError: (err, info) => {
const errorPolicy = resolveTelegramErrorPolicy({
cfg,
channel: "telegram",

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.

P1 Badge Apply error policy to delivered error payloads

This policy is only consulted inside the dispatcher onError callback, but that callback runs only when deliver throws (src/auto-reply/reply/reply-dispatcher.ts catches await options.deliver(...) failures). Provider/rate-limit failures that are turned into normal isError reply payloads and delivered successfully never hit this path, so repeated provider error messages are still sent to chats and the new anti-spam behavior does not activate for its primary scenario.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1b768b2997

ℹ️ 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 on lines +98 to +99
errorPolicy: TelegramErrorPolicySchema,
errorCooldownMs: z.number().int().nonnegative().optional(),

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.

P2 Badge Sync Telegram config TS types with new error policy fields

These schema additions make errorPolicy/errorCooldownMs valid at runtime, but the exported Telegram config interfaces are not updated (src/config/types.telegram.ts still omits these properties on account/group/direct/topic configs). In TypeScript configs (for example openclaw.config.ts using satisfies OpenClawConfig), users will get "property does not exist" errors when using the new options, forcing unsafe casts and undermining the feature’s typed config workflow.

Useful? React with 👍 / 👎.

obviyus pushed a commit to chinar-amrutkar/openclaw that referenced this pull request Apr 1, 2026
…sages

Introduces per-account error policy configuration that can suppress
repetitive error messages (e.g., 429 rate limit, ECONNRESET) to
prevent noisy error floods in Telegram channels.

Closes openclaw#34498
obviyus added a commit that referenced this pull request Apr 1, 2026
…-amrutkar)

* feat(telegram): add error policy for suppressing repetitive error messages

Introduces per-account error policy configuration that can suppress
repetitive error messages (e.g., 429 rate limit, ECONNRESET) to
prevent noisy error floods in Telegram channels.

Closes #34498

* fix(telegram): track error cooldown per message

* fix(telegram): prune expired error cooldowns

* fix: add Telegram error suppression controls (#51914) (thanks @chinar-amrutkar)

---------

Co-authored-by: chinar-amrutkar <[email protected]>
Co-authored-by: Ayaan Zaidi <[email protected]>
@chinar-amrutkar
chinar-amrutkar deleted the feature/telegram-error-policy branch April 1, 2026 21:41
lovewanwan pushed a commit to lovewanwan/openclaw that referenced this pull request Apr 28, 2026
…chinar-amrutkar)

* feat(telegram): add error policy for suppressing repetitive error messages

Introduces per-account error policy configuration that can suppress
repetitive error messages (e.g., 429 rate limit, ECONNRESET) to
prevent noisy error floods in Telegram channels.

Closes openclaw#34498

* fix(telegram): track error cooldown per message

* fix(telegram): prune expired error cooldowns

* fix: add Telegram error suppression controls (openclaw#51914) (thanks @chinar-amrutkar)

---------

Co-authored-by: chinar-amrutkar <[email protected]>
Co-authored-by: Ayaan Zaidi <[email protected]>
ogt-redknie pushed a commit to ogt-redknie/OPENX that referenced this pull request May 2, 2026
…chinar-amrutkar)

* feat(telegram): add error policy for suppressing repetitive error messages

Introduces per-account error policy configuration that can suppress
repetitive error messages (e.g., 429 rate limit, ECONNRESET) to
prevent noisy error floods in Telegram channels.

Closes openclaw#34498

* fix(telegram): track error cooldown per message

* fix(telegram): prune expired error cooldowns

* fix: add Telegram error suppression controls (openclaw#51914) (thanks @chinar-amrutkar)

---------

Co-authored-by: chinar-amrutkar <[email protected]>
Co-authored-by: Ayaan Zaidi <[email protected]>
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request May 9, 2026
…chinar-amrutkar)

* feat(telegram): add error policy for suppressing repetitive error messages

Introduces per-account error policy configuration that can suppress
repetitive error messages (e.g., 429 rate limit, ECONNRESET) to
prevent noisy error floods in Telegram channels.

Closes openclaw#34498

* fix(telegram): track error cooldown per message

* fix(telegram): prune expired error cooldowns

* fix: add Telegram error suppression controls (openclaw#51914) (thanks @chinar-amrutkar)

---------

Co-authored-by: chinar-amrutkar <[email protected]>
Co-authored-by: Ayaan Zaidi <[email protected]>
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request May 24, 2026
…chinar-amrutkar)

* feat(telegram): add error policy for suppressing repetitive error messages

Introduces per-account error policy configuration that can suppress
repetitive error messages (e.g., 429 rate limit, ECONNRESET) to
prevent noisy error floods in Telegram channels.

Closes openclaw#34498

* fix(telegram): track error cooldown per message

* fix(telegram): prune expired error cooldowns

* fix: add Telegram error suppression controls (openclaw#51914) (thanks @chinar-amrutkar)

---------

Co-authored-by: chinar-amrutkar <[email protected]>
Co-authored-by: Ayaan Zaidi <[email protected]>
Nachx639 pushed a commit to Nachx639/clawdbot that referenced this pull request Jun 17, 2026
…chinar-amrutkar)

* feat(telegram): add error policy for suppressing repetitive error messages

Introduces per-account error policy configuration that can suppress
repetitive error messages (e.g., 429 rate limit, ECONNRESET) to
prevent noisy error floods in Telegram channels.

Closes openclaw#34498

* fix(telegram): track error cooldown per message

* fix(telegram): prune expired error cooldowns

* fix: add Telegram error suppression controls (openclaw#51914) (thanks @chinar-amrutkar)

---------

Co-authored-by: chinar-amrutkar <[email protected]>
Co-authored-by: Ayaan Zaidi <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

channel: telegram Channel integration: telegram size: S

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant