Search code examples
c#wcftransactionsmsmqpoison

MSMQ WCF Transactional Queue Message going to Poison Queue after proccessing when no error is occurring in developer code


This isn't actually a question. Rather an answer for anyone having the same problem as it took me 2 days to figure out what was going wrong.

Scenario: We have a transactional MSMQ queue that we recieve messages via WCF with TransactionScopeRequired = true, TransactionAutoComplete = true

When a message is received, it is handled normally in our code without error, but then the 'AbortCount' of the message increases and it's sent to the retry queue or the poison queue depending on your MSMQ binding configuration. No errors are thrown in our code and it should have been processed successfully.

The following exception occurs outside of any developer code, and only shows up when 'just my code' is disabled.

The transport channel detected a poison message. This occurred because the message exceeded the maximum number of delivery attempts or because the channel detected a fundamental problem with the message. The inner exception may contain additional information.

Turns out what was happening was in my message processing code, I was starting a DB transaction, and then neither committing it (due to no changes) nor rolling it back (incorrectly). This caused the ambient WCF transaction to detect an aborted transaction, and rollback.

Solution: Don't just dispose a transaction if you aren't committing it! All transactions must be commited or rolled back. This might be obvious to some, but you don't know what you don't know.


Solution

  • Call Transaction.Comit() to commit the transaction, instead of letting it be disposed incomplete. I also noticed that the MSMQ ambient transaction didn't like it if you called .Rollback in an inner transaction.