Skip to content

Stat analysis

Media error or link error? What SCSI sense codes and Linux ATA log lines can and cannot tell apart

Published 2026-10-10

A SATA drive that fails to read a sector and a SATA cable that corrupts a transfer are separated by two bits in the ATA error register: UNC (0x40, a media error, reported only after the drive's own retries) maps to SCSI sense key 03h MEDIUM ERROR with ASC/ASCQ 11h/04h, while ICRC with ABRT (0x84) maps to sense key 0Bh ABORTED COMMAND with 47h/00h and, in Linux, to the log text 'ATA bus error' (Emask 0x10). The separation is lossy: the Linux translation table collapses every link CRC into one SCSI parity code although the T10 list has separate codes for data-phase CRC (47h/01h) and UDMA CRC (08h/03h), a bus error clears the device and media bits of the same command, and a timeout (Emask 0x4) says only that the controller got no answer. Linux changes link speed after more than 3 bus or timeout errors in 10 minutes, but media errors are not counted by any of those rules.

Path analysed
SATA drive behind a Linux libata host: ATA status and error registers, then libata's own error mask, then the SCSI sense data the SCSI layer sees
Standard reference
T10 numeric ASC/ASCQ assignment list, as of 2024-11-28
Kernel reference
torvalds/linux master, HEAD 3857c2fe5449 at access on 2026-10-10
Not covered
SAS-native sense reporting from real drives, hardware RAID controllers, tape drive logs, any measured rates

From ATA error bits to SCSI sense data

Rows of the table libata uses to turn an ATA status or error register value into SCSI sense data (sense key, additional sense code and qualifier, all in hex). The T10 text is the name T10 gives to that code. The last column is the cause class the code name implies.
ATA register value (hex)ATA meaning (include/linux/ata.h)Sense key (hex)ASC/ASCQ (hex)T10 name of that codeClassSource
error 0x40UNC: uncorrectable media error03h MEDIUM ERROR11h/04hUNRECOVERED READ ERROR - AUTO REALLOCATE FAILEDmediaLinux kernel source
error 0x84ICRC with ABRT: interface CRC error0Bh ABORTED COMMAND47h/00hSCSI PARITY ERROR (T10 lists data-phase CRC separately as 47h/01h)linkLinux kernel source
error 0x01AMNF: address mark not found03h MEDIUM ERROR13h/00hADDRESS MARK NOT FOUND FOR DATA FIELDmediaLinux kernel source
error 0x10IDNF: ID not found05h ILLEGAL REQUEST21h/00hLOGICAL BLOCK ADDRESS OUT OF RANGEaddressing (a media-format cause is not distinguished)Linux kernel source
status DF bitDevice fault04h HARDWARE ERROR44h/00hINTERNAL TARGET FAILUREdeviceLinux kernel source
status BSY bitDevice busy, error bits invalid0Bh ABORTED COMMAND00h/00hNO ADDITIONAL SENSE INFORMATIONunknownLinux kernel source

Codes T10 assigns that separate link from media

Entries from the T10 ASC/ASCQ list that name a media cause, a link cause, or an internal device cause for direct-access (disk) devices. 'Class' is a reading of the name, not a T10 statement.
ASC/ASCQ (hex)T10 nameApplies to disks (D)ClassSource
11h/00hUNRECOVERED READ ERRORyesmediaT10 ASC/ASCQ list
11h/01hREAD RETRIES EXHAUSTEDyesmediaT10 ASC/ASCQ list
0Ch/02hWRITE ERROR - AUTO REALLOCATION FAILEDyesmediaT10 ASC/ASCQ list
47h/01hDATA PHASE CRC ERROR DETECTEDyeslinkT10 ASC/ASCQ list
47h/03hINFORMATION UNIT iuCRC ERROR DETECTEDyeslinkT10 ASC/ASCQ list
08h/03hLOGICAL UNIT COMMUNICATION CRC ERROR (ULTRA-DMA/32)yeslinkT10 ASC/ASCQ list
44h/00hINTERNAL TARGET FAILUREyesdevice internalT10 ASC/ASCQ list
5Dh/00hFAILURE PREDICTION THRESHOLD EXCEEDEDyesprediction flag, not a faultT10 ASC/ASCQ list

What the kernel log line means

The libata error mask (Emask) printed in 'exception' and 'res' lines, with the meaning given by the kernel wiki and the string the current libata-eh.c prints for it.
Emask (hex)String printedMeaning per kernel wikiKernel action per libata-eh.cSource
0x10ATA bus errorChip-to-device bus errorReset scheduled; DEV, MEDIA and INVALID bits of the same command are cleared as probably spuriousKernel ATA wiki
0x8media errorSoftware detected a media errorSet from the UNC or AMNF error bit; no reset by this ruleLinux kernel source
0x4timeoutController failed to respond to an active command; wiki says any number of causesReset scheduled; counted toward speed-downKernel ATA wiki
0x2HSM violationHardware did not respond as the host state machine expectsReset scheduled; counted toward speed-downKernel ATA wiki
0x1device errorError delivered directly by the drive; many of them often means a hardware problemCounted as unknown-device error only if not MEDIA or INVALIDKernel ATA wiki

When Linux reacts to link-type errors

The speed-down rules in libata-eh.c, as coded. Windows are in minutes and thresholds are counts of errors of the named categories within the window.
Counted errorsWindow (min)Threshold (errors)ActionSource
ATA bus or timeout/HSM10more than 3Lower the link speedLinux kernel source
Timeout/HSM or unknown device10more than 3Turn NCQ offLinux kernel source
Unknown device10more than 6Lower the link speedLinux kernel source
ATA bus, timeout/HSM and unknown device, combined5more than 6Fall back to PIOLinux kernel source
Media errors (UNC, AMNF)nonenoneCategory 0 (ATA_ECAT_NONE); none of the rules reads itLinux kernel source

Reading the numbers

The first thing to read in a failing SATA read is not the sense key but the ATA error register. UNC (0x40) is reported by the drive only after it has used its own retries, and libata turns it into 03h MEDIUM ERROR with 11h/04h; ICRC with ABRT (0x84) is a transfer that arrived damaged and becomes 0Bh ABORTED COMMAND with 47h/00h. The kernel wiki reads these the same way: UNC as 'often due to bad sectors on the disk', ICRC as 'often either a bad cable or power problem'. The two sources agree on the split but both say 'often', so it is a pointer, not a diagnosis.

Three details limit the split. First, the SCSI side loses information: libata maps every interface CRC to 47h/00h SCSI PARITY ERROR, although T10 lists data-phase CRC (47h/01h), iuCRC (47h/03h) and UDMA CRC (08h/03h) as separate codes, so a tool that only reads sense data cannot tell which link layer was involved. Second, when a command ends with an ATA bus error, libata-eh.c clears the device, media and invalid-argument bits of that command; a media problem on the same command is therefore not logged beside the bus error. Third, IDNF is shown as 05h ILLEGAL REQUEST with 21h/00h (LBA out of range), a name that points to addressing, not to a damaged sector.

A timeout (Emask 0x4) and an HSM violation (0x2) are the least informative lines. The kernel wiki says a timeout may have 'any number of causes', and the same lines drive the speed-down counters as bus errors do. The T10 code 5Dh/00h, FAILURE PREDICTION THRESHOLD EXCEEDED, is a drive-side flag, not an observed fault, and it appears in neither the libata translation table nor the kernel's sense-key handling read for this note.

The kernel reacts differently to the two classes. After more than 3 bus or timeout errors in 10 minutes it lowers the link speed, and after more than 6 combined errors in 5 minutes it falls back to PIO. Media errors get no such treatment: the scsi_error.c handler returns a final disposition for a MEDIUM ERROR with ASC 11h, 13h or 14h and marks it as a medium error, and tries again only for other ASC values. The practical reading is that a log full of bus errors with a link that drops speed is a different situation from a log with scattered UNC lines, and the code treats them as such; whether a given drive's cause is a cable, a backplane, power or the drive's own interface is not something these fields settle.

Related: the SMART failure-signal note,the NVMe health-log noteand what fails most often on HDDs, SSDs and links.

Method

Every code and number was copied on 2026-10-10 from a source that was opened that day: the Linux kernel files drivers/ata/libata-scsi.c (ATA-to-SCSI sense translation table), drivers/ata/libata-eh.c (error strings, bus-error handling, speed-down rules), drivers/scsi/scsi_error.c (per-sense-key disposition), include/scsi/scsi_proto.h (sense key values) and include/linux/ata.h (error register bits), read from the master branch (HEAD 3857c2fe5449541e24afc5efdb0f81a8a8f9a3a0 at access time); the T10 numeric ASC/ASCQ list (dated by T10 as of 2024-11-28); and the archived ata.wiki.kernel.org page on libata error messages. The kernel tree and the T10 list are independent publications: one says what Linux does, the other what the standard assigns. Tables give each code in the form the source prints it (hex) and name the source in the last column. Where Linux and T10 disagree, the table shows both.

Limits

Linux behaviour is read from source on the master branch on one date; older kernels, other operating systems, hardware RAID firmware and drives that report native SCSI sense (SAS) are not covered, and no log from a real failing drive was analysed, so no failure rate or detection rate is stated. The T10 list gives code names and the device types they apply to; it does not say which physical fault produces which code, so the class column in Table 2 is a reading of the code name, not a T10 statement. The archived kernel wiki says its content is obsolete; it was used only for the Emask and error-bit meanings, which the current libata-eh.c strings match. The comment above the speed-down rules in libata-eh.c says more than 8 combined bus, timeout or unknown-device errors in 5 minutes trigger a PIO fallback, while the code tests more than 6; the table follows the code. Drive-internal causes behind a timeout or a device fault are not visible in any of these fields. Nothing here covers NVMe (see the NVMe health-log note), tape drive logs, or any prediction of failure.

Sources

  1. 01Linux kernel: drivers/ata/libata-scsi.c, drivers/ata/libata-eh.c, drivers/scsi/scsi_error.c, include/scsi/scsi_proto.h, include/linux/ata.h (master, HEAD 3857c2fe5449) · accessed 2026-10-10
  2. 02T10: SCSI ASC/ASCQ assignments, numeric sorted listing (as of 2024-11-28) · accessed 2026-10-10
  3. 03Libata error messages, ata Wiki (archived, marked obsolete) · accessed 2026-10-10