Reliable healthcare messaging requires confirmation that messages were received and processed correctly. HL7 v2 uses acknowledgement messages (ACK) to provide this confirmation, paired with codes that indicate whether the message was accepted (AA), accepted with soft errors (AE), or rejected (AR). Understanding HL7 acknowledgements is essential for building robust, error-tolerant interfaces.
What is an ACK / NACK
An acknowledgement (ACK) message is an HL7 message sent by the receiving system to confirm that it has received and processed a message from a sending system. An ACK message has a message type of ACK, and it contains the MSA (Message Acknowledgment) segment, which carries the acknowledgement code and optional error details.
Technically, HL7 v2 does not use the term "NACK" (Negative Acknowledgement); instead, it uses ACK with different codes to indicate success or failure. However, in practice, the term NACK is often used colloquially to refer to an ACK message with a rejection code (AE or AR).
The general workflow is:
- Sender transmits a message (e.g., ADT^A01 patient admission)
- Receiver parses the message and attempts to process it
- Receiver constructs an ACK message with:
- The original message's control ID (to allow the sender to correlate ACK with request)
- An acknowledgement code (AA, AE, or AR) indicating the outcome
- Optional ERR segments describing any errors or warnings
- Receiver transmits the ACK to the sender
- Sender receives the ACK and either confirms success or retransmits the original message with corrections
This synchronous or semi-synchronous acknowledgement pattern is fundamental to reliable healthcare messaging. Senders can configure their systems to raise alerts if an expected ACK is not received within a timeout window, triggering retransmission or escalation.
AA, AE, AR Codes
The MSA-1 field (acknowledgement code) uses a controlled vocabulary to indicate the outcome of message processing. There are three primary codes:
AA (Application Acknowledgment - Accept)
Meaning: The message was received, parsed, and processed without errors. No corrective action is needed on the sender's side.
When to use: Send AA when the entire message has been successfully ingested into your system and all business logic (e.g., patient was admitted, order was recorded, result was stored) has completed without problem.
Example: A hospital admitting system receives an ADT^A01 patient admission message, validates all required fields, creates a new patient record, and sends back an ACK with code AA to confirm success.
AE (Application Acknowledgment - Error)
Meaning: The message was received and some processing occurred, but soft errors were encountered. The message may be partially accepted, or certain fields may not have been processed correctly, but the system did not reject the entire message outright. The sender should review the ERR segments and may resubmit a corrected version.
When to use: Send AE when the message contains data that does not conform to your system's rules, but the core message can still be acted upon. For example, a laboratory result message arrives with an invalid unit code for one result, but other results in the message are valid. Send AE with an ERR segment explaining the invalid unit, and process the valid results.
Soft errors often include:
- Missing optional fields
- Unrecognized coded values (but the message is still processable)
- Data that is technically valid but semantically unusual (e.g., a discharged patient being re-admitted)
- Fields that fail validation but have sensible defaults
Example: A pharmacy system receives an ORM (order message) with a medication order; the order is valid, but the patient's allergy field is incomplete. The system sends back an ACK^AE with an ERR segment noting the missing allergy information, and it records the order while flagging it for manual review.
AR (Application Acknowledgment - Reject)
Meaning: The message was received but could not be processed at all. A hard error (one that prevents message consumption or storage) was detected, and the message was rejected in its entirety. The sender should not resubmit the message unless it is corrected.
Hard errors include:
- Missing required fields
- Syntax errors that prevent parsing (though these are rare in HL7 v2)
- Rejection based on business rules (e.g., an unknown patient ID, an invalid order type)
- System unavailability or resource exhaustion
When to use: Send AR when the message cannot be processed, stored, or acted upon in any way. The entire message must be corrected and resubmitted.
Example: An EHR system receives an ADT message with a missing or unrecognized patient identifier. The system cannot create a patient record without a valid ID, so it sends back an ACK^AR with an ERR segment describing the missing identifier. The source system must correct the patient ID and resubmit.
Original Mode vs Enhanced Mode
HL7 v2 defines two acknowledgement modes, selectable via the MSH-15 and MSH-16 fields:
Original Mode (MSH-15 only)
In Original Mode, the sender requests acknowledgement by setting MSH-15 (Accept Acknowledgment Type). The receiver responds with a single ACK message that confirms receipt and basic validation.
-
MSH-15 values:
- AL (Always): Always send an ACK, whether success or failure
- NE (Never): Do not send an ACK
- SU (Success): Send an ACK only if the message is processed successfully (AA)
- ER (Error): Send an ACK only if an error occurs (AE or AR)
-
Limitations: Original Mode provides only basic acknowledgement. The receiver cannot separate "message received" from "message processed successfully." If the receiver system crashes after receiving a message but before processing it, the sender does not learn of the problem from the ACK.
Enhanced Mode (MSH-15 and MSH-16)
In Enhanced Mode, the sender can request both accept-level acknowledgement (MSH-15) and application-level acknowledgement (MSH-16). This allows the receiver to confirm two distinct events: receipt and parsing on one hand, and application processing on the other.
- MSH-15 (Accept Acknowledgment Type): Sent immediately upon receipt and parsing of the message, before business logic executes. Codes: AL, NE, SU, ER.
- MSH-16 (Application Acknowledgment Type): Sent after the application has attempted to process the message. Codes: AL, NE, SU, ER.
Example Enhanced Mode workflow:
- Sender transmits ORM (order message) with MSH-15 = AL, MSH-16 = AL
- Receiver's transport layer receives the message, parses it, and immediately sends an ACK with MSA-1 = AA (accept acknowledgement)
- Receiver's application logic processes the order (records it in the database, validates against allergies, etc.)
- Receiver's application layer sends a second ACK with MSA-1 = AA or AE (application acknowledgement) depending on whether business logic succeeded
Enhanced Mode is more reliable but more complex. It requires the receiver system to support two separate acknowledgement events and the sender to handle multiple ACKs per request. Most operational healthcare systems use Original Mode for simplicity.
Sample ACK Message
Minimal ACK (Original Mode):
MSH|^~&|LAB|LABFACILITY|EHR|HOSPITAL|20260701120500||ACK^A01^ACK|ACK001|P|2.5.1
MSA|AA|MSG001
Breakdown:
- MSH: Standard message header for an ACK message
- MSH-3: LAB (receiving system, now sending)
- MSH-4: LABFACILITY
- MSH-5: EHR (original sender, now receiving)
- MSH-6: HOSPITAL
- MSH-7: 20260701120500 (timestamp when ACK was created)
- MSH-9: ACK^A01^ACK (message type; the second component echoes the trigger event of the original message)
- MSH-10: ACK001 (unique control ID for this ACK)
- MSH-11: P (processing ID, inherited from original)
- MSH-12: 2.5.1 (version, same as original)
- MSA-1: AA (acknowledgement code: accepted)
- MSA-2: MSG001 (control ID of the original message being acknowledged)
ACK with Error (Enhanced Mode):
MSH|^~&|LAB|LABFACILITY|EHR|HOSPITAL|20260701120530||ACK^ORM^O01^ACK|ACK002|P|2.5.1|1||AL|AL
MSA|AE|ORM001|E|8001^Unknown patient ID^HL70357
ERR||CX|||E||8001^Unknown patient ID. Patient record does not exist in receiving system.^HL70357
Breakdown:
- MSH-15: AL (Always send accept acknowledgement)
- MSH-16: AL (Always send application acknowledgement)
- MSA-1: AE (Error: message was received but application processing failed)
- MSA-2: ORM001 (control ID of the original order message)
- MSA-3: E (Error severity code)
- MSA-4: 8001^Unknown patient ID^HL70357 (HL7 error code from terminology.hl7.org table 0357)
- ERR: Additional error details in the ERR segment
MSA Segment Breakdown
The MSA (Message Acknowledgment) segment carries the core acknowledgement information. Its fields are:
| Field | Name | Type | Description |
|---|---|---|---|
| MSA-1 | Acknowledgement Code | ID | AA (accept), AE (error), or AR (reject) |
| MSA-2 | Message Control ID | ST | Control ID of the message being acknowledged (from MSH-10 of the original message) |
| MSA-3 | Text Message | ST | Optional human-readable error or status message |
| MSA-4 | Expected Sequence Number | NM | Expected next message sequence number (for batching) |
| MSA-5 | Delayed Acknowledgement Type | ID | Type of delay, if this ACK is sent asynchronously (D = delayed) |
| MSA-6 | Error Condition | CWE | HL7 error code (from table 0357) describing the error (optional, use if MSA-1 is AE or AR) |
| MSA-7 | Segment ID | ST | If present, identifies a specific segment that caused the error |
| MSA-8 | Segment Sequence | NM | Position of the problematic segment in the original message |
| MSA-9 | Error Location | ERL | Field and component location of the error, if known |
MSA-1 (Acknowledgement Code): Always required. Must be AA, AE, or AR.
MSA-2 (Message Control ID): Always required. Must match MSH-10 from the original message so the sender can correlate the ACK with its request.
MSA-3 (Text Message): Optional. Provides a human-readable description, useful for operations staff debugging. Example: "Patient not found; verify MRN."
MSA-6 (Error Condition): Optional but recommended when MSA-1 is AE or AR. Use an HL7 error code (CWE data type) from the standard error vocabulary to enable automated error handling. Example: 8001 (Unknown patient ID), 8002 (Message parsing error), 8003 (Rule violation).
ERR Segment: While technically a separate segment, ERR typically follows MSA and provides detailed error information. One ERR segment can describe a single error; multiple ERR segments can list multiple errors. The ERR segment includes the segment ID, field position, error code, and a descriptive message.
Error Handling Best Practices
For Senders (Systems Transmitting Messages):
-
Set Correct Acknowledgement Expectations: Set MSH-15 and MSH-16 appropriately. Use AL (always) if you need to know every outcome; use SU (success only) if you care only about success confirmation; use ER (error only) if you have retry logic and want to know only about problems.
-
Implement Timeout Logic: Do not wait indefinitely for an ACK. Set a timeout (e.g., 30 seconds) and, if no ACK arrives, log an alert and retry the message (with a limit on retries to prevent flood). This protects against lost ACKs or silent failures of the receiving system.
-
Correlate by Message Control ID: Store the MSH-10 (message control ID) of each sent message and match it against MSA-2 in the ACK. Never assume ACKs arrive in the same order as messages are sent. A receiving system might process messages out of order if it is multi-threaded.
-
Parse Error Codes: Read MSA-1 and MSA-6 to determine the outcome. If the code is AA, confirm success. If AE or AR, read the ERR segment to identify the problem and decide whether to retry or escalate.
-
Log All ACKs: Even successful ACKs (AA) should be logged for audit and troubleshooting. Include timestamp, message type, control ID, and acknowledgement code in the log.
For Receivers (Systems Processing Messages):
-
Parse and Validate Before Responding: Parse the incoming message fully, validate required fields, and check business rules before generating an ACK. A hasty ACK that accepts an invalid message wastes everyone's time later.
-
Send Detailed Error Information: When sending AE or AR, include an ERR segment with the specific error. Use standard error codes (table 0357) and provide enough detail that the sender can correct the problem. Example: "Invalid medication code 'ASPIRIN999'; valid codes are ASPIRIN, ACETAMINOPHEN, IBUPROFEN."
-
Use Appropriate Severity Levels: In the ERR segment, use severity codes: W (warning, soft error, continue processing), E (error, consider message compromised), or I (information, not an error). This helps the sender distinguish between recoverable and non-recoverable problems.
-
Acknowledge Every Message: Even if you reject a message, send an ACK. Do not silently discard messages. The sender will wait for the ACK and eventually time out if it does not arrive, which is worse than a fast rejection.
-
Handle Resubmissions: If the sender resubmits a message after receiving an AE or AR, treat it as a new message. Do not automatically suppress duplicates just because the control ID is the same; business logic may have changed, or the correction may be intentional. (However, do implement duplicate detection at a higher layer if needed for audit reasons.)
For Both Sides:
-
Document Your Acknowledgement Policy: Specify which messages require acknowledgement and what acknowledgement types you support (Original vs Enhanced Mode). Document in your interface specifications what codes you generate and how you respond to each code.
-
Test Error Scenarios: Test not only happy-path messages but also error cases. Send a message with missing required fields and verify that the receiver sends AE or AR. Send a message with valid syntax but semantically wrong data (e.g., a discharge for a non-existent patient) and verify the receiver's error response.
-
Monitor for Orphaned ACKs: If an ACK arrives for a message you did not send, log it and investigate. This could indicate a timing issue, duplicate processing, or misconfigured system IDs.
-
Plan for Performance: Acknowledgements are critical to flow control. If a receiver takes 10 seconds to generate an ACK for each message, the sender can send at most 1 message every 10 seconds (if it waits for ACK before sending the next one). Use asynchronous acknowledgement (MSA-5 = D) if you need to separate receipt from processing for performance reasons.
Related pages
- HL7 Introduction: History, the v2 Family, and Why It Still Dominates
- HL7 Message Structure: Segments, Fields, Components, and Delimiters
- HL7 v2 Versions: Timeline 2.1 to 2.8.2 and Which to Use
- MSA Segment: Message Acknowledgment
- ERR Segment: Error Segment
