Fix LINE webhook retryable acknowledgement#102141
Conversation
|
Codex review: found issues before merge. Reviewed July 15, 2026, 11:21 PM ET / July 16, 2026, 03:21 UTC. Summary PR surface: Source +467, Tests +942, Docs +10. Total +1419 across 14 files. Reproducibility: yes. at source level. The existing early-ACK class and the patch’s immediate-rejection behavior are clear from the handlers and supplied HTTP transcript, while the reviewer’s lifecycle trace establishes the remaining delayed pre-adoption ambiguity. Review metrics: 2 noteworthy metrics.
Root-cause cluster Members:
Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything. Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Rank-up moves:
Risk before merge
Maintainer options:
Next step before merge
Maintainer decision needed
Security Review findings
Review detailsBest possible solution: Preserve Do we have a high-confidence way to reproduce the issue? Yes at source level. The existing early-ACK class and the patch’s immediate-rejection behavior are clear from the handlers and supplied HTTP transcript, while the reviewer’s lifecycle trace establishes the remaining delayed pre-adoption ambiguity. Is this the best way to solve the issue? No. The LINE-specific machinery is useful, but interpreting callback or promise settlement inside the channel is not the narrowest maintainable fix; it should consume a canonical core per-event outcome and preserve the shipped default unless maintainers approve migration. Full review comments:
Overall correctness: patch is incorrect AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against 957cc81175a3. Label changesLabel justifications:
Evidence reviewedPR surface: Source +467, Tests +942, Docs +10. Total +1419 across 14 files. View PR surface stats
What I checked:
Likely related people:
What the crustacean ranks mean
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics. How this review workflow works
Review history (7 earlier review cycles)
|
0680a15 to
1b98343
Compare
steipete
left a comment
There was a problem hiding this comment.
Requesting changes before this can land.
-
waitForLineWebhookDispatchAcceptance()treats a zero-delay timer as successfulafter_agent_dispatchacceptance. That only proves the promise stayed pending for one event-loop turn. An asynchronous failure during allowlist/media preparation, session recording, or dispatch admission can reject later, after all three HTTP paths have already sent 200; LINE then cannot redeliver. A webhook containing multiple events is weaker still, because the batch is acknowledged without proving that each later event reached a dispatch boundary.Please replace the timer heuristic with an explicit per-event acceptance signal from the inbound turn owner. The request should acknowledge only after every event is either accepted for agent dispatch or completes without requiring dispatch. Add regressions for a delayed pre-dispatch rejection and a multi-event callback.
-
The channel setup docs need to tell operators to enable Webhook redelivery in LINE Developers Console. LINE documents that redelivery is disabled by default and that non-2xx responses are redelivered only when it is enabled: receiving messages and webhook error/timeout behavior.
The intent is sound, and the shared Node/Express/monitor plumbing is a good direction. The current implementation does not yet uphold its declared acknowledgement policy, so I cannot land it at this head.
|
Maintainer follow-up after attempting the explicit per-event acceptance design locally: The necessary acceptance point is deeper than the current LINE callback surface. The inbound callback still runs before A correct fix needs a canonical reply-lane admission/durable receive contract exposed through the Plugin SDK, then LINE can aggregate that explicit result for every event in the webhook batch. The acceptance signal must occur only after the lane owns the turn; failures before that point must reject the webhook. Please keep the delayed-failure and multi-event regressions, and retain the operator docs for enabling LINE Webhook redelivery. I am not pushing the experimental local callback patch because it would only move the false-ack boundary rather than remove it. |
4907dcd to
331fe0e
Compare
34631c9 to
bc21c89
Compare
|
AI-assisted (approved by Peter) Thank you @NianJiuZst for identifying the retryable-ack loss mode and contributing the original work. The maintainer rework has landed in #109655, with your co-author credit preserved in the landed change. The landed fix uses the decided SQLite spool-first architecture: durable admission before HTTP 200, channel-owned retry/replay, and typed terminal dead-letter states. Closing this superseded PR in favor of the landed rework. |
What Problem This Solves
LINE webhook handlers acknowledged signed event requests before knowing whether local dispatch even started. If the handler rejected immediately, OpenClaw still returned 200, so LINE would not redeliver a retryable webhook even though the event was not accepted.
The same early-ACK shape existed in the standalone Express middleware, the Node webhook handler, and the shared multi-account monitor route.
Why This Change Was Made
This change introduces a bounded dispatch-acceptance step for LINE webhooks. Each entrypoint starts event handling, waits one event-loop turn to surface startup-time rejection as a 500 response, then acknowledges with 200 once dispatch is accepted. If processing continues asynchronously, later failures are still logged in the background instead of holding the provider HTTP response for the full agent turn.
The LINE message adapter now defaults to
after_agent_dispatchwhile preserving shippedafter_receive_recordsupport. The exported Node/Express handlers and shared monitor route have a realafter_receive_recordpath for compatibility, and unsupported policy inputs normalize to the default dispatch-acceptance behavior instead of hanging.User Impact
Immediate LINE webhook dispatch failures can now trigger provider redelivery instead of being swallowed behind a 200 response. Normal successful turns still ACK quickly after local dispatch starts, avoiding long webhook waits while the agent run continues. Existing consumers that inspect or choose
after_receive_recordremain compatible.Evidence
node scripts/run-vitest.mjs extensions/line/src/webhook-node.test.ts extensions/line/src/channel.sendPayload.test.ts extensions/line/src/monitor.lifecycle.test.ts(60 tests passed)node scripts/run-vitest.mjs extensions/line/src/bot-handlers.test.ts(28 tests passed)createLineNodeWebhookHandler:status=200, body{"status":"ok"}, response returned before the pending handler was releasedstatus=500, body{"error":"Internal server error"}git diff --check -- extensions/line/src/webhook-ack.ts extensions/line/src/webhook.ts extensions/line/src/webhook-node.ts extensions/line/src/outbound.ts extensions/line/src/webhook-node.test.ts extensions/line/src/channel.sendPayload.test.ts extensions/line/src/monitor.ts extensions/line/src/monitor.lifecycle.test.ts docs/channels/line.md.agents/skills/autoreview/scripts/autoreview --mode local(clean after preservingafter_receive_recordsupport and narrowing/normalizing the exposed ACK policy)Remote Testbox proof was not run from this checkout because the local Crabbox wrapper selected binary
0.18.0, whileblacksmith-testboxrequires Crabbox>=0.22.0.