HL7 v2 message validation
Check messages against the HL7 2.9 specification - required fields, datatypes and vendor quirks.
Validation runs two ways - during parsing, where the first problem raises an exception, or standalone with validate_message, which collects every problem into one result. Both check the same rules from the HL7 2.9 specification: required fields must be present and field values must match their declared datatypes. This page covers both, plus the tolerance switches that repair almost-correct vendor messages before the checks run.
Validation during parsing
Parsing validates by default - the first field-level problem raises HL7ValidationError:
# Zato
from zato.hl7v2 import parse_hl7, HL7ValidationError
raw = (
'MSH|^~\\&|SENDER|FACILITY|RECEIVER|FAC|20260315||ADT^A01^ADT_A01|CTL001|P|2.9\r'
'EVN|A01\r' # <- EVN-2 (recorded date/time) is required but missing
'PID|1||12345^^^HOSP^MR||SMITH^JOHN||19800115|M\r'
'PV1|1|I\r'
)
try:
message = parse_hl7(raw)
except HL7ValidationError as e:
... # Message validation failed: EVN.1.2: Missing required field EVN.2
Pass validate=False to accept any message that parses, which is the usual choice for real-world feeds that do not strictly follow the specification:
The parser itself is lenient - a message missing a whole segment still parses, and segments the structure does not declare are skipped. The one structural error it does raise is ValueError for an MSH-9 that names no known message structure:
raw = 'MSH|^~\\&|SENDER|FACILITY|RECEIVER|FAC|20260315||QQQ^Z99^QQQ_Z99|CTL001|P|2.9\r'
parse_hl7(raw, validate=False)
# ValueError: Parse error: Unknown message structure
Collect every problem at once
Use validate_message when one exception per message is not enough - it returns a ValidationResult with is_valid, errors and warnings, and every problem is in the list:
# Zato
from zato.hl7v2 import validate_message
result = validate_message(raw)
if not result.is_valid:
for error in result.errors:
print(error.path) # 'EVN.1.2'
print(error.code) # 'REQUIRED_FIELD'
print(error.message) # 'Missing required field EVN.EVN.2 (EVN.2)'
The result is truthy when the message is valid, so if validate_message(raw): works too.
Datatype problems are reported the same way - a non-numeric value in a field declared as SI (sequence ID) produces an error with the code INVALID_DATATYPE and the message Expected datatype 'SI', got 'XXXXXXXXXX'.
Tolerance for vendor quirks
Vendor systems routinely send messages that are almost correct - carriage returns embedded in field values, invalid escape sequences, placeholder text. A ToleranceConfig repairs such input before parsing and validation run, so both can pass without changing what the sender emits:
# Zato
from zato.hl7v2 import parse_hl7, ToleranceConfig
tolerance = ToleranceConfig()
tolerance.strip_embedded_cr_from_fields = True
tolerance.normalize_invalid_escape_sequences = True
message = parse_hl7(raw, validate=True, tolerance=tolerance)
The available switches include, among others:
normalize_invalid_escape_sequences- fix backslash sequences that are not valid HL7 escapesstrip_embedded_cr_from_fields- remove carriage returns embedded inside field valuesnormalize_unescaped_delimiters- handle delimiter characters used as literal textforce_standard_delimiters- rewrite non-standard delimiter declarations to^~\&strip_placeholder_text_from_fields- drop placeholder values such as""markers, with the patterns configurable throughplaceholder_patternsnormalize_obx2_value_typeandreplace_invalid_obx2_value_type- repair OBX-2 value typescoded_field_mappings- map vendor-specific codes to standard ones per field
MLLP channels expose the same switches in their configuration, so the identical repairs can run on traffic received over the wire - the channel configuration reference lists them all with their defaults.
See also
| Page | What it covers |
|---|---|
| Parsing and serialization | parse_hl7 and the validate flag in context |
| Field access | Reading and writing the fields validation checks |
| Channel configuration | The same tolerance switches on MLLP channels |
Learn more
Schedule a meaningful demo
Book a demo with an expert who will help you build meaningful systems that match your ambitions
"We evaluated 12 integration platforms and Zato was the only one to score 100%."
Philip Zuñiga, Assistant Professor, University of the Philippines