Skip to content

Write the Alert Dispatched event when an alert value is null - #573

Open
pacmano1 wants to merge 2 commits into
OpenIntegrationEngine:mainfrom
pacmano1:fix/572-alert-dispatched-null
Open

pacmano1 wants to merge 2 commits into
OpenIntegrationEngine:mainfrom
pacmano1:fix/572-alert-dispatched-null

Conversation

@pacmano1

@pacmano1 pacmano1 commented Nov 11, 2026 •

Copy link
Copy Markdown
Contributor

Closes #572.

When an alert fires, its actions go out first. Then AlertWorker.ActionTask builds the "Alert Dispatched" event by calling toString() on every value in the alert's context. A null value throws, and the task runs on an executor whose Future nobody reads, so the event is never written and nothing is logged.

It's not only the server name. A source transformer that throws, or a call to alerts.sendAlert(...), leaves connectorType null, and those alerts never wrote the event either, server name or not. Measured below.

The blank server name case is courtesy of #259, which put serverName in the context. Tony spotted the null in review, wrote a nice paragraph about it, and it still collected three approvals, with #47 lined up to fill it in. #47 is still lined up. In fairness, the toString() loop that actually throws has been sitting there since Mirth.

Change

  • A null context value becomes an empty attribute, Objects.toString(value, ""). AuthorizationController does the same for audit events, and empty is also what the feat: add serverName variable on alert template #259 thread wanted for the template variable.
  • The event step gets the same try/catch and logger.error the protocol and email steps in that method already have, so if it breaks again it says so.
  • Alert templates are untouched. With no server name set, ${serverName} still renders as the literal token, as discussed in feat: add serverName variable on alert template #259, and so does ${connectorType} on transformer and alerts.sendAlert alerts. Checked on an engine built from this branch.
  • Heads-up for upgrades: alerts on transformer errors or alerts.sendAlert, and any alert on a server with no name, will start writing an "Alert Dispatched" event per action. They never did before. Each one carries the full error text in error and errorMessage, same as the events that were already being written.

AlertWorkerTest covers a null server name and connector type, a set server name, and a failing dispatch getting logged. The first and the last fail on main.

How to verify

Fresh engine on Derby, no server name set (Settings, Server, Server Name empty).

  1. Create a channel "Receiver": Channel Reader source, any destination.
  2. Create a channel "Throws": Channel Reader source, JavaScript Writer destination with throw new Error('boom');.
  3. Create a channel "Transformer Throws": Channel Reader source with a JavaScript transformer step throw new Error('transformer boom');, any destination.
  4. Create an alert on any error for "Throws" and "Transformer Throws", with a Channel action to "Receiver". Enable it and deploy all three channels.
  5. Send a message to "Throws".
  6. Set a Server Name and save. Send a message to "Transformer Throws".
  7. Look in Events for "Alert Dispatched".

Before: "Receiver" gets both alert messages, but neither "Alert Dispatched" event is written, and mirth.log says nothing about it. After: both events are there, with serverName blank on the first and connectorType blank on the second.

Tested

./gradlew clean build -x signSetupJars: 913 tests, 0 failures, 0 skipped.

Live on Derby, one engine built from main (cd802ef) and one from this branch, one message per row:

Scenario Alert action delivered (main / this PR) Alert Dispatched event (main / this PR)
No server name, JavaScript Writer throws yes / yes missing / written, serverName blank
Server name set, JavaScript Writer throws (control) yes / yes written / written
Server name set, source transformer throws yes / yes missing / written, connectorType blank
Server name set, alerts.sendAlert(...) yes / yes missing / written, connectorType blank

On main, mirth.log has nothing about the three missing events. On this branch the new error line never shows up, since nothing failed.

Release Note

The "Alert Dispatched" event is no longer skipped when an alert value is missing

When an alert fired, its actions went out, but the "Alert Dispatched" event wasn't written if one of the alert's values was missing, and nothing was logged. That happened for any error alert while Settings, Server, Server Name was blank, and for alerts on source transformer errors or alerts.sendAlert(...), which carry no connector type. The event is now written with those values as empty attributes, and a failure to write it is logged. (#572, #573)

After upgrading, installs with such alerts will see "Alert Dispatched" events they didn't get before. Alert templates are unchanged: with no server name set, ${serverName} still renders as the literal ${serverName}.

Co-authored with Claude Code.

AlertWorker.ActionTask built the event by calling toString() on every
alert context value, so a null value threw after the alert's actions had
gone out. Nothing reads the task's Future, so the event was dropped and
nothing was logged. A blank server name (since OpenIntegrationEngine#259) and a null connector
type (source transformer errors, alerts.sendAlert) both hit it.

Null values now become empty attributes, as AuthorizationController does
for audit events, and a failure in the event step is logged like the
protocol and email steps already are.

Closes OpenIntegrationEngine#572

Signed-off-by: Finnegan's Owner <44065187+pacmano1@users.noreply.github.com>
Co-Authored-By: Claude <noreply@anthropic.com>
@github-actions

github-actions Bot commented Nov 11, 2026 •

Copy link
Copy Markdown

Test Results

  143 files  +1    143 suites  +1   4m 2s ⏱️ +48s
  940 tests +3    940 ✅ +3  0 💤 ±0  0 ❌ ±0 
1 102 runs  +3  1 096 ✅ +3  6 💤 ±0  0 ❌ ±0 

Results for commit 7f9ca4f. ± Comparison against base commit cd802ef.

♻️ This comment has been updated with latest results.

mgaffigan
mgaffigan previously approved these changes Nov 11, 2026
tonygermano
tonygermano previously approved these changes Nov 12, 2026
@tonygermano

Copy link
Copy Markdown
Member

@pacmano1 I already approved, but can you add a release note section to the bottom of the PR description?

@pacmano1

Copy link
Copy Markdown
Contributor Author

Added.

@jonbartels jonbartels 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.

Logging improvement. I hate to reject the PR for it but a clear log will help a lot in the event that this does throw.

A question or nit - The "How to verify" section describes a channel setup that would validate the issue. Should this be a smoke test channel? I am leaning "no" since the unit test seems sufficient

}
eventController.dispatchEvent(serverEvent);
} catch (Exception e) {
logger.error("Error dispatching the Alert Dispatched event.", e);

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.

Will this exception include useful information to know:

  • what alert failed?
  • why it failed?

Eg should this say something like "Error dispatching the alert dispatched event for serverID xxxxx for event zzzz"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if this is necessary. The logging framework already knows which server produced the log entry.

Alerts have an id, but I don't know if that is in any way useful. There is not an event to reference because that is the thing that failed.

@tonygermano tonygermano Nov 13, 2026 •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Alert Dispatched" is the event type. See line 212 in this file.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added the alert's name and id: Error dispatching the Alert Dispatched event for alert "<name>" (<id>). Forced the dispatch to fail on a running engine to check it: mirth.log shows that line, then the exception and its stack trace. On the smoke test question, agreed, no.

Co-authored with Claude Code.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jonbartels I agree. Especially as the dude always complaining about the use of logger.* throwing stuff to the console leaving me asking "where did that come from and why didn't some prepend the channelName and maybe location in the channel?".

If writing the Alert Dispatched event fails, the error now says which alert
it was, as "name" (id), the way the engine names channels in its log lines.
The exception is still attached.

Signed-off-by: Finnegan's Owner <44065187+pacmano1@users.noreply.github.com>
Co-Authored-By: Claude <noreply@anthropic.com>
@pacmano1
pacmano1 dismissed stale reviews from tonygermano and mgaffigan via 7f9ca4f November 13, 2026 18:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Alert Dispatched event is not written when an alert value is null

4 participants