T024

How do I prevent beforeAcceptTask from silently dropping the action on second attempt?

Ticket

Hi Twilio Support, We're running Flex UI 2.7.1 with a custom plugin (let's call it TaskAcceptPlugin) deployed in our current active release. I wanted to check whether there's a recommended pattern for retrying a failed beforeAcceptTask override, because we're seeing some confusing behavior that I'm not sure is expected. Here's the setup: in our plugin we register a beforeAcceptTask handler that makes a short fetch call to our internal API to log some metadata before the task is accepted. Most of the time this works fine. The issue appears when that fetch call fails with a network hiccup — our code catches the error and displays a toast to the agent, then returns without calling the `payload.reject()` callback explicitly (we assumed not calling reject would let the action fall through or allow a retry). What actually happens: 1. Agent receives a reservation (WR4xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, TaskQueue WQbxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx). 2. The agent clicks Accept. 3. The fetch to our API fails; we catch it and show the toast. 4. The AcceptTask action appears to silently swallow — no FlexError is surfaced, the Flex console shows no 45600/45601 code, and the reservation just sits in a pending state on the UI. 5. If the agent clicks Accept a second time, nothing happens at all — the button becomes unresponsive. The reservation eventually times out and the task gets re-evaluated. We verified via `Flex.Monitor.getErrors()` immediately after the second click and it returns an empty array, which is what's confusing us — we would have expected a FlexError to appear there if the action framework was rejecting internally. Repro steps (consistent across Chrome 124 and Edge 124): - Simulate a network failure on the fetch inside beforeAcceptTask by blocking the URL in DevTools. - Click Accept on an inbound voice task. - Observe toast fires, but action appears to hang. - Click Accept again. - Button does nothing; no error logged to Flex Monitor. Worker SID for our test agent: WK3xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx. I can also share the configuration SID for the release if that helps — just let me know. So my questions are: 1. Is there a supported way to 'reset' the AcceptTask action so the agent can retry after a beforeAcceptTask failure? 2. Is it expected that a beforeAcceptTask handler that neither resolves cleanly nor calls reject would leave the action framework in a stuck state like this? It's causing us moderate pain because affected agents have to refresh their entire Flex tab to get the reservation back, and by then the reservation has often timed out. We're happy to add explicit reject/resolve handling if that's the fix, but wanted to confirm first whether this stuck-state behavior on the second click is intentional or something we should escalate. Thanks in advance for any guidance.

Gold label: bug / high

this pattern is repeatable for any agent logging in, so would have a higher business impact

Results by run

openai · gpt-5.5

2026-10-04 17:23 UTC · prompt ef0017a

config (wrong)
medium (wrong)
escalate: no

Summary

A custom Flex plugin's beforeAcceptTask logic can leave task acceptance pending when the customer-owned API call fails and the handler does not explicitly settle or abort the action.

Suggested first response

Thanks for the detailed repro. Based on the behavior, this looks most likely to be caused by the custom plugin leaving the AcceptTask action in an in-flight state when the internal API call fails. Please update the beforeAcceptTask handler so every code path settles deterministically: continue only after the logging call succeeds, and explicitly abort/reject the action on failure rather than returning silently. Also confirm in the browser Network/Console tabs that the failing request is to your internal API, and capture a Flex Status Report if the issue persists after adding explicit settle/abort handling. If AcceptTask still becomes unresponsive with a minimal plugin that always resolves or explicitly aborts, we can escalate that as a potential Flex UI action-framework issue. Until then, the reservation timing out and being re-evaluated is consistent with TaskRouter behavior when it remains pending.

KB citations

kb-007, kb-015, kb-008

1227 output tokens · 15.0s · 1 attempt(s)

anthropic · claude-sonnet-4-6

2026-10-04 17:20 UTC · prompt ef0017a

how_to (wrong)
medium (wrong)
escalate: no

Summary

Customer's Flex plugin leaves the AcceptTask action in a stuck/unresponsive state when a beforeAcceptTask handler fails without explicitly calling payload.reject(), and they want to know the supported pattern for handling retries.

Suggested first response

Thank you for the detailed write-up — this is a well-understood behavior of the Flex Action framework. When a beforeAcceptTask handler neither resolves cleanly nor explicitly calls payload.reject(), the Action framework treats the action as still in-flight and does not reset its internal state. This is expected behavior, not a platform defect. The supported fix is to always call payload.reject() (or throw an error) in your catch block when you want to abort the action — this signals to the framework that the action has terminated, which re-enables the Accept button and allows a retry. A recommended pattern is: (1) in your catch block, call payload.reject() after displaying the toast so the framework knows the action was aborted; (2) optionally, re-invoke Flex.Actions.invokeAction('AcceptTask', payload) programmatically if you want an automatic retry rather than requiring the agent to click again. Because payload.reject() was never called, the framework held the action open, which is why Flex.Monitor.getErrors() returned empty (no FlexError was generated — the action simply never completed). The reservation timeout behavior you observed is consistent with kb-008: a timed-out reservation is not lost, it returns to queue for re-evaluation. To avoid agents needing to refresh, ensure every code path in your beforeAcceptTask handler either allows the action to proceed or explicitly calls payload.reject().

KB citations

kb-007, kb-008

400 output tokens · 10.3s · 1 attempt(s)