Press Releases
J1939 DM1 vs DM2: Understanding Diagnostic Messages
September 3, 2026
Anyone working with SAE J1939 fault reporting runs into DM1 and DM2 almost immediately — they're the two most common diagnostic messages on the bus, and they're easy to confuse because they carry nearly identical data structures. The difference isn't in what they contain, it's in what state of fault they represent. This guide breaks down exactly how DM1 and DM2 differ, how each is structured, and when a real diagnostic workflow needs to look at one versus the other.
DM1 (PGN 65226) reports currently active diagnostic trouble codes — faults that are happening right now. DM2 (PGN 65227) reports previously active diagnostic trouble codes — faults that occurred at some point but are not currently present. Both messages use the same underlying data structure (SPN, FMI, Occurrence Count, SPN Conversion Method); the distinction is purely about fault status, not format.
DM1, formally Active Diagnostic Trouble Codes, is defined in J1939-73 as PGN 65226. An ECU broadcasts DM1 whenever it has one or more faults that are currently active — meaning the fault condition is present at this exact moment. If the fault clears (e.g., a sensor reading returns to normal range), the associated code is expected to drop out of the next DM1 broadcast.
DM2, formally Previously Active Diagnostic Trouble Codes, is defined in J1939-73 as PGN 65227. It holds a history of faults that were active at some point but are no longer occurring — essentially the fault memory log. This is the equivalent of what many technicians call "stored codes" or "history codes" in other diagnostic contexts.
| Aspect | DM1 | DM2 |
|---|---|---|
| Full name | Active Diagnostic Trouble Codes | Previously Active Diagnostic Trouble Codes |
| PGN | 65226 | 65227 |
| Defined in | J1939-73 | J1939-73 |
| Reports | Faults currently occurring | Faults that occurred but are no longer active |
| Transmission | Broadcast on change / cyclically (e.g., 1 s) | Sent on request |
| Data structure | SPN + FMI + OC + SPN Conversion Method | Same structure as DM1 |
| Lamp status included | Yes | Yes |
| Cleared by | Fault condition resolving on its own | DM3 (Clear Previously Active DTCs) command |
| Typical use case | Real-time fault monitoring, dash warning lamps | Fault history review, service diagnostics |
Both messages share the same on-wire structure. The first byte carries lamp status, and every DTC after that is packed into a repeating 4-byte block:
| Byte(s) | Field |
|---|---|
| Full name | Active Diagnostic Trouble Codes |
| Byte 1 | Lamp Status (MIL, Red Stop, Amber Warning, Protect) |
| Byte 2 | Flash/Lamp Status continued |
| Bytes 3-4 | SPN (low byte, mid byte — partial) |
| Byte 5, bits 1-5 | FMI |
| Byte 5, bits 6-7 | SPN Conversion Method |
| Byte 5, bits 8 + Byte 6 | SPN (high bits) / Occurrence Count |
If more than one fault is active (or was previously active), the message extends beyond 8 bytes and is sent using the Transport Protocol (TP.CM/TP.DT), since a single CAN frame can't hold more than one 8-byte payload. This is one of the most common places implementations get tripped up — a DM1 with multiple simultaneous faults is a multi-packet message, not a single frame, and needs to be reassembled accordingly.
Suppose an engine ECU detects a boost pressure sensor reading a voltage above the expected range, starting at time T:
This is exactly why fleet diagnostic tools query both messages: DM1 tells you what's wrong right now, DM2 tells you what's happened since the last clear.
DM1 and DM2 are the two most commonly used diagnostic messages, but J1939-73 defines a broader family:
| Message | Purpose |
|---|---|
| DM1 | Active Diagnostic Trouble Codes |
| DM2 | Previously Active Diagnostic Trouble Codes |
| DM3 | Clear Previously Active DTCs (technician command) |
| DM4 | Freeze Frame Parameters |
| DM11 | Clear/Reset Active DTCs (technician command) |
| DM12 | Emissions-Related Active DTCs |
| DM23 | Previously Active Emissions-Related DTCs |
| DM30 | Scaled Test Results |
| DM31 | DTC to Lamp Association |
DM1 and DM2 handle the general case; several of the others (like DM12/DM23) exist specifically for emissions-related fault reporting under OBD requirements.
For anyone building or integrating a J1939 stack, treating DM1 and DM2 as interchangeable is a common source of bugs:
A properly implemented Diagnostic Event Manager handles this separation natively — tracking active faults, moving them into history when they clear, and responding to DM3/DM11 clear requests — rather than requiring application code to manage the state transitions manually.