openclaw - ✅(Solved) Fix Discord exec approval buttons silently fail after 2-minute timeout (no user feedback) [1 pull requests, 3 comments, 4 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#49282Fetched 2026-04-08 00:56:59
View on GitHub
Comments
3
Participants
4
Timeline
5
Reactions
0
Author
Timeline (top)
commented ×3cross-referenced ×2

Discord exec approval buttons appear to do nothing when clicked if more than 2 minutes have elapsed since the approval was sent. There is also a secondary bug where the failure follow-up message crashes, preventing any error feedback from reaching the user.


Error Message

agent UNAVAILABLE TypeError: entry.factory is not a function runId=exec-approval-followup:5e22c2ad-33b7-4896-9a84-ab5b40310954

Root Cause

Discord exec approval buttons appear to do nothing when clicked if more than 2 minutes have elapsed since the approval was sent. There is also a secondary bug where the failure follow-up message crashes, preventing any error feedback from reaching the user.


Fix Action

Fixed

PR fix notes

PR #49825: Discord: make exec approval timeout configurable

Description (problem / solution / changelog)

Summary

  • Problem: Discord exec approvals always expired after 2 minutes, even for operators approving from mobile notifications or slower workflows.
  • Why it matters: the timeout was hardcoded in the exec approval request path, so Discord config had no way to extend it.
  • What changed: added channels.discord.execApprovals.timeoutMs, wired channel-owned timeout resolution into approval registration, updated schema/docs, and added focused tests.
  • What did NOT change (scope boundary): this PR does not address the separate async follow-up entry.factory is not a function failure also mentioned in #49282.

Change Type (select all)

  • Bug fix
  • Feature
  • Refactor
  • Docs
  • Security hardening
  • Chore/infra

Scope (select all touched areas)

  • Gateway / orchestration
  • Skills / tool execution
  • Auth / tokens
  • Memory / storage
  • Integrations
  • API / contracts
  • UI / DX
  • CI/CD / infra

Linked Issue/PR

  • Related #49282

User-visible / Behavior Changes

  • New optional config: channels.discord.execApprovals.timeoutMs
  • Discord exec approval requests now honor the configured timeout instead of always using 120000ms

Security Impact (required)

  • New permissions/capabilities? (Yes/No) No
  • Secrets/tokens handling changed? (Yes/No) No
  • New/changed network calls? (Yes/No) No
  • Command/tool execution surface changed? (Yes/No) No
  • Data access scope changed? (Yes/No) No
  • If any Yes, explain risk + mitigation:

Repro + Verification

Environment

  • OS: macOS
  • Runtime/container: local dev checkout
  • Model/provider: n/a
  • Integration/channel (if any): Discord
  • Relevant config (redacted): channels.discord.execApprovals.timeoutMs: 600000

Steps

  1. Configure Discord exec approvals with a longer timeoutMs.
  2. Trigger an exec request that requires approval.
  3. Observe that the approval stays pending for the configured interval instead of expiring after 2 minutes.

Expected

  • Discord exec approval timeout is configurable per account.

Actual

  • Before this change, the approval request path always used 120000ms.

Evidence

Attach at least one:

  • Failing test/log before + passing after
  • Trace/log snippets
  • Screenshot/recording
  • Perf numbers (if relevant)

Trace/log summary:

  • pnpm exec oxfmt --check ... passed on touched files
  • pnpm exec oxlint ... reported 0 warnings/errors on touched TS files
  • pnpm tsgo still reports unrelated pre-existing repo failures outside this diff
  • local vitest / codex review did not complete cleanly in this environment, so this PR does not claim a passing runtime test run here

Human Verification (required)

What you personally verified (not just CI), and how:

  • Verified scenarios: traced the request path from Discord config -> channel adapter -> exec approval registration payload and confirmed the configured timeout is threaded through to exec.approval.request
  • Edge cases checked: missing/invalid timeout falls back to the default; non-Discord surfaces continue using the default timeout
  • What you did not verify: a successful end-to-end Vitest or live Discord run in this local environment

Review Conversations

  • I replied to or resolved every bot review conversation I addressed in this PR.
  • I left unresolved only the conversations that still need reviewer or maintainer judgment.

Compatibility / Migration

  • Backward compatible? (Yes/No) Yes
  • Config/env changes? (Yes/No) No
  • Migration needed? (Yes/No) No
  • If yes, exact upgrade steps:

Failure Recovery (if this breaks)

  • How to disable/revert this change quickly: remove channels.discord.execApprovals.timeoutMs or revert this commit
  • Files/config to restore: Discord exec approval config and the touched exec approval request plumbing
  • Known bad symptoms reviewers should watch for: approval requests ignoring the configured timeout or expiring immediately

Risks and Mitigations

  • Risk: a non-Discord channel could accidentally inherit Discord-specific timeout behavior
  • Mitigation: timeout resolution goes through the generic channel adapter and falls back to the default

AI-assisted: yes (Codex)

Changed files

  • docs/channels/discord.md (modified, +3/-0)
  • extensions/discord/src/channel.ts (modified, +3/-0)
  • extensions/discord/src/exec-approvals.ts (modified, +24/-1)
  • src/agents/bash-tools.exec-approval-request.test.ts (modified, +80/-1)
  • src/agents/bash-tools.exec-approval-request.ts (modified, +38/-13)
  • src/agents/bash-tools.exec-host-gateway.ts (modified, +4/-0)
  • src/agents/bash-tools.exec-host-node.ts (modified, +4/-0)
  • src/agents/bash-tools.exec-host-shared.test.ts (added, +58/-0)
  • src/agents/bash-tools.exec-host-shared.ts (modified, +14/-1)
  • src/channels/plugins/types.adapters.ts (modified, +5/-0)
  • src/config/config.discord.test.ts (modified, +30/-0)
  • src/config/schema.help.ts (modified, +2/-0)
  • src/config/schema.labels.ts (modified, +1/-0)
  • src/config/types.discord.ts (modified, +2/-0)
  • src/config/zod-schema.providers-core.ts (modified, +1/-0)
  • src/infra/exec-approval-surface.test.ts (modified, +92/-4)
  • src/infra/exec-approval-surface.ts (modified, +30/-0)
  • src/infra/exec-approvals.ts (modified, +7/-0)

Code Example

07:47:24 exec.approval.waitDecision 119918ms  ← timed out
07:47:52 exec.approval.waitDecision 119967ms  ← timed out
07:51:12 exec.approval.resolveINVALID_REQUEST: unknown approval id  ← user clicked, already expired
07:53:42 exec.approval.waitDecision 119942ms  ← timed out

---

"execApprovals": {
  "enabled": true,
  "approvers": ["784467315068502098"],
  "target": "channel",
  "timeoutMs": 600000
}

---

await interaction.followUp({
  content: `Failed to submit approval decision for **${decisionLabel}**. The request may have expired or already been resolved.`,
  ephemeral: true
});

---

agent UNAVAILABLE TypeError: entry.factory is not a function
  runId=exec-approval-followup:5e22c2ad-33b7-4896-9a84-ab5b40310954
RAW_BUFFERClick to expand / collapse

Bug Report

Version: checked against current dist (discord-DnPCmCxV.js)

Summary

Discord exec approval buttons appear to do nothing when clicked if more than 2 minutes have elapsed since the approval was sent. There is also a secondary bug where the failure follow-up message crashes, preventing any error feedback from reaching the user.


Bug 1: Hardcoded 2-minute approval timeout with no config option

DEFAULT_APPROVAL_TIMEOUT_MS is hardcoded at 12e4 (120 seconds) and is not exposed in DiscordExecApprovalConfig. On mobile (Discord app), it is common to receive the notification and tap the button after 2 minutes have passed — especially if the phone was locked or the user was in another app.

Evidence from gateway logs (all waitDecision entries resolve at ~119–120 s, never via an actual button click):

07:47:24 exec.approval.waitDecision 119918ms  ← timed out
07:47:52 exec.approval.waitDecision 119967ms  ← timed out
07:51:12 exec.approval.resolve ✗ INVALID_REQUEST: unknown approval id  ← user clicked, already expired
07:53:42 exec.approval.waitDecision 119942ms  ← timed out

Requested fix: expose timeoutMs in DiscordExecApprovalConfig so operators can configure a longer window. A reasonable default might be 10 minutes for mobile users. Example:

"execApprovals": {
  "enabled": true,
  "approvers": ["784467315068502098"],
  "target": "channel",
  "timeoutMs": 600000
}

Bug 2: entry.factory is not a function crash silences the expired-approval ephemeral

When exec.approval.resolve returns INVALID_REQUEST, the ExecApprovalButton.run() handler attempts to send an ephemeral follow-up:

await interaction.followUp({
  content: `Failed to submit approval decision for **${decisionLabel}**. The request may have expired or already been resolved.`,
  ephemeral: true
});

But the gateway logs show this agent crashes before delivery:

agent UNAVAILABLE TypeError: entry.factory is not a function
  runId=exec-approval-followup:5e22c2ad-33b7-4896-9a84-ab5b40310954

The result: the user clicks a button and sees nothing at all — no acknowledgment, no error. From the user's perspective the buttons are completely broken.

Requested fix: investigate entry.factory is not a function in the exec-approval-followup agent path.


Impact

  • Every Discord exec approval on a slow/mobile connection silently expires
  • User has no way to know the approval timed out vs. the button being broken
  • "Allow Always" is effectively unreachable without sub-2-minute response time

Platform: macOS 14, Discord iOS mobile as the approver channel

extent analysis

Fix Plan

To address the issues, we will:

  • Expose timeoutMs in DiscordExecApprovalConfig to allow operators to configure a longer approval window.
  • Fix the entry.factory is not a function error in the exec-approval-followup agent path.

Step 1: Expose timeoutMs in DiscordExecApprovalConfig

Update the DiscordExecApprovalConfig interface to include timeoutMs:

interface DiscordExecApprovalConfig {
  enabled: boolean;
  approvers: string[];
  target: string;
  timeoutMs: number; // add this line
}

Set a reasonable default value for timeoutMs, e.g., 10 minutes:

const defaultConfig: DiscordExecApprovalConfig = {
  enabled: true,
  approvers: [],
  target: 'channel',
  timeoutMs: 600000, // 10 minutes
};

Step 2: Fix entry.factory is not a function error

Investigate the exec-approval-followup agent path and ensure that entry.factory is properly defined. If entry.factory is not a function, it may be due to a missing import or incorrect initialization. For example:

import { factory } from './factory';

// ...

const entry = {
  factory, // ensure factory is properly assigned
  // ...
};

Alternatively, you can try to log the entry object to see its actual structure and identify the issue:

console.log(entry);

Step 3: Update the approval timeout logic

Update the approval timeout logic to use the configured timeoutMs value:

const timeoutMs = config.timeoutMs;
// ...
setTimeout(() => {
  // timeout logic
}, timeoutMs);

Verification

To verify the fix, test the approval buttons on a mobile device with a slow connection. Ensure that the buttons respond correctly even after the initial 2-minute timeout. Additionally, test the error handling by simulating an expired approval and verifying that the ephemeral follow-up message is sent correctly.

Extra Tips

  • Consider adding logging to track approval timeouts and errors to help identify issues.
  • Review the approval logic to ensure it is robust and handles various edge cases.
  • Test the fix thoroughly on different platforms and devices to ensure compatibility.

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