Skip to content

message_sent hook not fired when message_sending hook cancels delivery #16596

@dashed

Description

@dashed

Summary

When a message_sending plugin hook cancels outbound delivery (returns { cancel: true }), the message_sent hook is not fired. This means plugins tracking delivery outcomes — audit logging, analytics, delivery confirmation — have no visibility into cancelled sends.

Severity

Medium — Affects plugins relying on message_sent for comprehensive delivery tracking. The send is correctly prevented, but the cancellation is silent to downstream observers.

Steps to Reproduce

  1. Register a plugin with both message_sending and message_sent hooks:
    api.on("message_sending", (event) => {
      if (shouldBlock(event.content)) return { cancel: true };
    });
    api.on("message_sent", (event) => {
      console.log("SENT HOOK:", event.success, event.error);
    });
  2. Trigger an outbound message through deliverOutboundPayloads (proactive/tool send path).
  3. Have the message_sending hook return { cancel: true }.

Expected

message_sent fires with { success: false, error: "canceled by message_sending hook" }.

Actual

message_sent does not fire. The cancellation is invisible to message_sent subscribers.

Root Cause

In src/infra/outbound/deliver.ts (line 488-489), when sendingResult?.cancel is true, the code does continue without calling emitMessageSent:

if (sendingResult?.cancel) {
  continue;  // BUG: skips emitMessageSent entirely
}

Context

Fix

One-line addition — fire emitMessageSent(false, "canceled by message_sending hook") before the continue:

if (sendingResult?.cancel) {
  emitMessageSent(false, "canceled by message_sending hook");
  continue;
}

A fix with 6 new tests (25 total passing) exists on branch fix/message-sent-hook-cancel-path.

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    staleMarked as stale due to inactivity

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions