Acknowledgments and Negative Acknowledgments (Part 1)

The Biztalk engine has the notion of publishing system level (positive) Acknowledgments (ACK’s) which indicate a successful message transmission and Negative Acknowledgments (NACK’s) which indicate the suspension of a message; these are extremely powerful and can be used for handling the outcomes of asynchronous operations in the engine. For example, consider the scenario whereby an Orchestration transmits a one-way message over HTTP, the Orchestration will publish the message to the Message Box which will route it to the appropriate send port. The transmission of the message is completely decoupled from the Orchestration publishing to the Message Box, so the Orchestration has no notion of whether the transmission actually succeeded or not, instead the Orchestration only knows whether the message was successfully published to o the Message Box. Perhaps the back end web server was down which caused the message to be suspended by the Biztalk engine. The Orchestration would have no way to determine the message was never delivered without some higher level message exchange in the form of a business Acknowledgment. Enter ACK’s and NACK’s.


If an Orchestration port is marked with Delivery Notification = Transmitted, and the Send shape in the Orchestration is in a synchronized scope, the Orchestration will wait until it either receives an ACK or a NACK for the message that was transmitted. In the case that the message was successfully transmitted, the engine will publish an ACK ensuring that it is routed back to that Orchestration instance, once the Orchestration receives the ACK it will leave the scope and continue processing. If however the transmission failed and the message was suspended, the engine will publish a NACK which again will be routed back to the Orchestration instance, the Orchestration will throw a DeliveryFailureException which can of course be caught and handled as appropriate in the Orchestration.  


ACK’s are published when the Messaging Engine successfully transmits a message over the ‘wire’ and the system context property “AckRequired” is written on the message that was sent and it is set to true. Providing the port in the Orchestration is mark as above the context property is automatically written by the engine so thee is no need to worry about setting it. NACK’s are published when ever the engine suspends a message. Both ACK’s and NACK’s have the following system context properties promoted which can therefore be used in filter expressions for routing:



AckType: set to ACK or NACK

AckID: set to the message ID of the message that this ACK/NACK is for

AckOwnerID: set to the instance ID that this ACK/NACK is for

CorrelationToken: flowed from the message to the ACK/NACK

AckSendPortName: the name of the send port that this message was being sent over

AckOutboundTransportLocation: the outbound url that this message was being sent over

AckReceivePortName: the name of the receive port that the message was received over

AckInboundTransportLocation: the inbound url that the message was received over



In addition all of the message context properties from the message that is being ACK’d / NACK’d are demoted (i.e. if they were previously promoted they will not be promoted on the ACK/NACK) and flowed and from the message to the ACK/NACK. ACK messages do not have any message parts, but of course the message context has a lot of important meta-data. NACK’s on the other hand as well as having all the useful meta-data in the form of context properties, have a message body part the content of which is a SOAP Fault, the format the SOAP Fault can be seen below, it should be noted that the exception message from the exception that the adapter raised is in the SOAP Detail section in the ErrorDescription element:


<SOAP:Envelope xmlns:SOAP=”” SOAP:encodingStyle=””>



                  <faultcode>Microsoft BizTalk Server Negative Acknowledgment</faultcode>

                  <faultstring>An error occurred while processing the message, refer to the details section for more information</faultstring>



                        <ns0:NACK Type=”NACK” xmlns:ns0=””>




                        <ErrorDescription>The FILE send adapter cannot open file C:\Foo\DeliveryNotification\out\{505A3211-9081-4720-827B-A0DE2BD124FD}.xml for writing.</ErrorDescription>








In the case of an Orchestration port marked as delivery notification required, the DeliveryFailureException that is thrown on a transmission failure is deserialized from the SOAP Fault that is contained within the NACK message body, this is of course transparent to the Orchestration. The Orchestration may get at the exception message string that was thrown by the adapter by casting the DeliveryFailureException to a SoapException and then accessing the InnerXml from the SOAP Detail section, this is shown below:



// Cast the DeliveryFailureException to a SoapException…

System.Web.Services.Protocols.SoapException se = (System.Web.Services.Protocols.SoapException)e.InnerException;



Returns the following Xml fragment…

<ns0:NACK Type=”NACK” xmlns:ns0=””>




      <ErrorDescription>The FILE send adapter cannot open file C:\Foo\DeliveryNotification\out\{505A3211-9081-4720-827B-A0DE2BD124FD}.xml for writing. </ErrorDescription>




The publication of ACK’s/NACK’s is a little bit special in that if there are no active subscriptions for them, the ACK/NACK will be discarded. The ACK/NACK is published atomically with the appropriate message, for example, the suspension of a message and the publication of its NACK are in the same transaction within the engine, similarly the publication of an ACK is performed in the same transaction as the deletion of the message from the application queue. Further the engine does not suspend ACK’s/NACK’s.


If the processing of a request-response message exchange pair fails after the receive adapter has successfully submitted the request message and the message is subsequently suspended, a NACK will be routed back to the waiting two-way receive adapter, the receive adapter may then transmit the fault message back to the client. Of course this means that the client would receive a SOAP Fault, what if the client doesn’t understand SOAP Faults? For these scenarios the SOAP Fault maybe mapped changing the format to one that the client is expecting and can handle. Also, once the initial request message is accepted, a processing failure anywhere in the engine resulting in the message being suspended will result in the NACK being routed back to the adapter as its response.


By now you are hopefully starting to appreciate the power of ACK’s and NACK’s, aside from the Orchestration delivery notification and the request-response scenarios above there are many scenarios where they are extremely useful. For example, suppose we have a scenario whereby we use a specific send port to transmit PO’s over a million dollars while all other PO’s are transmitted using a different send port. We could use a filter expression on a send port to route any NACK’s published for messages that are suspended whilst being transmitted on that send port which could subsequently be processed by some backend system.


Alternatively, an Orchestration with a direct binding to the Message Box could be built to receive all NACK’s and subsequently perform some processing to handle the failure based on where the failure happened. Which brings me nicely to Part 2! In Part 2 I’ll describe how such a generic NACK Handler Orchestration may be built which could be used to handle suspended messages, for example moving those messages from the Biztalk applications suspended queue to some out of band application that could handle those failures, along with a sample NACK Handler I’m currently developing, so stay tuned for Part 2 in the near future. 

Comments (24)

  1. David Stampfli says:

    Great post. I’m looking forward to part 2.

  2. Paul Brown says:

    Awesome post – opens up the engine in how it handles ack/nacks. Thanks 🙂

  3. Ricky Davis says:

    Great info! Looking forward to the next part 🙂

  4. JD says:

    Good post, but I think I am missing something and could use some help. I have a one way port with property Delivery Notification=Transmitted. I have a scope shape set to sychronized=true and set to long running. On the scope I have an exception block of type Microsoft.XLANGs.BaseTypes.DeliveryFailureException and name of e. Inside the exception block I try to casting the exception to a SoapException within a expression shape (using your sample code snipet) and keep getting a "illegal declarator" declaration may appear only in a service or scope…any ideas? Am I approaching this wrong?

  5. Hmm, try it in user code, that’s what I did. When I get time I’ll see if I can get it working in an expression shape.

  6. Craig Beuker says:


    Spent some time looking at this briefly. I have noticed that I can only set the DeliveryNotification flag if the port binding type is "Specify Later" or "Dynamic". If I choose "Specify Now" for my port binding, I can’t set the DeliveryNotification property.

    I understand why I can’t do this for "Direct" port bindings, the documentation says so, but what’s the story with "Specify Now"? Am I missing something blindingly obvious (which is not beyond the realm of possibilities..), or is this a, erm, "feature", ya, feature, thats the word (**cough** bug **cough**)


  7. Saravana Kumar says:

    Hi Kevin,

    I guess there should be way around to handle "could not find matching subscription" error with ACK/NACK. Our scenario is like this.

    Biztalk receives the message from a receive location, some properties are promoted on the custom pipeline, it gets routed to the send port based on promoted properties (subscription filter). There is a possibility, the message might have reached Biztalk with incorrect values, in that case you’ll get an error in the event log saying "could not find matching subscription".

    We need to generate a custom error message and handle the following two scenarios

    1. Request-response Receive port. (Need to send the error back syncrhonously)

    2. One way receive port. ( Need to send back error asynchronusly on a different send port)

    I’m working on it at the moment. Any suggestions will be greatly appreciated

  8. For #1, the request-response scenario, I would recomend either a custom pipeline component in the response pipeline to ‘change the shape’ of the NACK into your prefered format, or use a map to map the Soap fault into your fault message. I’ve never tried tha map appraoch it should work, but the pipeline appraoch will definitely work.

    For #2, the one way port, I would recomend having an orchestration that subscribes to the NACK and publishes the async message to be sent.

    In part two of this article I’ll publish my helper utility that I’m finishing up, this will enable this scenario to be handled with close to no code. I’m pretty close to getting it finished.



  9. Evan says:

    Ping Back来自:老和山下

  10. Commonality says:

    When you are invoking WebServices from your BizTalk Server 2004 orchestrations, you might need to ensure that two things happen…

  11. Plenty of folks make the assumption that wrapping a couple BizTalk adapters in an atomic scope makes…

  12. Did anyone else read Kevin Smith&amp;#8217;s blog on ACK/NACK and run out to try it? Well, I sure did and