25.10: SMARTFailedSelfTest can never fire for NVMe β€” parse_nvme_smart_info reads the oldest log entry

While re-enabling SMART self-tests after the 25.10 upgrade migrated them to cron jobs, I read through middlewared/alert/source/smart.py to confirm what still reaches an operator now that the SMART UI is gone. The ATA and SCSI paths look right. The NVMe path reads the wrong end of the self-test log, and I believe it makes SMARTFailedSelfTest unreachable for NVMe devices.

Version: TrueNAS SCALE 25.10.5, smartmontools 7.4

The code

/usr/lib/python3/dist-packages/middlewared/alert/source/smart.py, the ATA parser, correctly takes the newest entry and says why:

# NAS-140419: smartctl writes table[] newest-first (see ataPrintSmartSelfTestlog
# in smartmontools/ataprint.cpp), so [0] is the most recent test.
test_failed = not ata_tests[0]["status"]["passed"]

The NVMe parser, two functions below, indexes from the opposite end:

def parse_nvme_smart_info(self, data: dict) -> SmartInfo:
    latest_entry = data.get("nvme_self_test_log", {}).get(
        "table", [{"self_test_result": {"value": -1}}]
    )[-1]
    return SmartInfo(
        smart_testfail=latest_entry["self_test_result"]["value"] in (5, 6, 7),
    )

[-1] is the last element β€” the oldest of the 20 retained entries β€” although the variable is named latest_entry. The result values (5, 6, 7) match the NVMe spec correctly (fatal/unknown error, failed segment unknown, failed segments); as far as I can tell only the index is wrong.

Reproduction

smartctl presents the NVMe self-test log newest-first, same as ATA. On an Intel Optane SSDPEK1A118GA:

$ sudo smartctl --json -l selftest /dev/nvme1 | jq '.nvme_self_test_log.table | {n: length, first: .[0], last: .[-1]}'
{
  "n": 20,
  "first": {
    "self_test_code":   { "value": 1, "string": "Short" },
    "self_test_result": { "value": 0, "string": "Completed without error" },
    "power_on_hours": 20011
  },
  "last": {
    "self_test_code":   { "value": 1, "string": "Short" },
    "self_test_result": { "value": 0, "string": "Completed without error" },
    "power_on_hours": 19555
  }
}

Index 0 is POH 20011 (most recent); index 19 is POH 19555 (oldest) β€” 456 power-on hours and 19 daily self-tests apart. The alert source is reading the 19555 entry.

This is not vendor-specific. Same ordering on every NVMe device in this system, across two vendors and two controller families:

Device Model table[0] POH table[-1] POH
nvme1 Intel Optane SSDPEK1A118GA 20011 19555
nvme2 Seagate IronWolf ZP2000NM30002 25144 24750
nvme3 Seagate IronWolf ZP2000NM30002 25135 24680

All three hold full 20-entry logs, all newest-first. nvme-cli’s nvme self-test-log, independent of smartctl, shows the same ordering β€” entry [0] carries the highest power-on-hours count.

Impact

Once a drive’s 20-entry log is full β€” which it is on any drive that has been self-testing for three weeks β€” a failure recorded at table[0] has to survive 20 further self-tests to reach the slot the parser examines. It ages out of the log before it gets there. So SMARTFailedSelfTest is registered, is driven by a live IntervalSchedule(timedelta(minutes=90)) poll, and still cannot fire for an NVMe device.

This matters more since 25.10 removed the SMART UI: there is no longer a screen where you’d notice the failed test yourself, and no smart/test/results endpoint to query, so the alert is the only path left. Anyone relying on it for NVMe drive health is not covered.

Suggested fix

Change [-1] to [0], mirroring parse_ata_smart_info. A regression test with a β‰₯2-entry NVMe log where only the newest entry has a failing result would pin the ordering β€” a single-entry fixture passes either way, which may be how this survived.

Happy to test a fix or provide more data from this system.

If you believe you found a Bug, submit the info using Report a Bug (GUI link or top right of forum) along with a debug dump and all the info in the post. Please post the ticket number or a link in this forum

Thanks. Created Jira

1 Like

Ticket above was closed as a Duplicate. Here’s a link to the other ticket.
https://ixsystems.atlassian.net/browse/NAS-140652

1 Like