Is it normal that a data flow task's OnError event handler fires 3x and how to avoid that? In an SSIS package there are event handlers on every data flow tasks which send an email with a brief description of the error. I fail the first task by introducing an error condition and get 3 emails.

Is there any way to avoid spamming the support staff with 3x the error messages and just send the first one (or if not possible, any one of the three)?

The first one is related to the actual SQL error condition:

SSIS Error Code DTS_E_OLEDBERROR.
An OLE DB error has occurred. Error code: 0x80004005.
An OLE DB record is available.  Source: "Microsoft OLE DB Provider for SQL Server"
Hresult: 0x80004005
Description: "The statement has been terminated.".
An OLE DB record is available.  Source: "Microsoft OLE DB Provider for SQL Server"
Hresult: 0x80004005
Description: "Violation of PRIMARY KEY constraint 'PK_Amount'. Cannot insert duplicate key in object 'dbo. Amount'. The duplicate key value is (2013, 10, 25000.00).".


It is followed by the second one:

SSIS Error Code DTS_E_INDUCEDTRANSFORMFAILUREONERROR.
The "Report.Inputs[OLE DB Destination Input]" failed because error code 0xC020907B occurred, and the error row disposition on "Report.Inputs[OLE DB Destination Input]" specifies failure on error.
An error occurred on the specified object of the specified component.
There may be error messages posted before this with more information about the failure.


And finally the last one:

SSIS Error Code DTS_E_PROCESSINPUTFAILED.
The ProcessInput method on component "Report" (29) failed with error code 0xC0209029 while processing input "OLE DB Destination Input" (42).
The identified component returned an error from the ProcessInput method.
The error is specific to the component, but the error is fatal and will cause the Data Flow task to stop running.
There may be error messages posted before this with more information about the failure.


I already experimented with replacing each task's OnError with the single package's OnError but that one does not seem to have access to the error's pertinent information.

Worst part is that the 1st two emails are arriving in random order. The 1st one arrives 1st slightly more often, but still randomly. The 3d one seems to be always last.
In my SSIS packages, I enclose the entire control flow in a sequence container, with a "Send Mail" task of the container's "on failure" flow.

In my error handlers, I collect the error information and append it to a string variable.

Then, in the "Send Mail" task, I include the string with the accumulated error information in the body of the message.

Now, this only works as is if the failure in your data flow is fatal to the package as a whole. If you're (for example) processing several files, and want to send out one error message for each file that fails its processing, you'd need to modify this to send the mail at the correct time, and clear the error detail variable; however, the same principle should apply.