Serious errors in log
What this check looks for
Error log entries containing error: 823,, error: 824, or error: 825, with a timestamp in the last two hours. Up to 100 are reported, each with its date and text.
The two hour window is deliberate. These are the errors you want to know about while they are happening, not as a monthly audit. The Error Log report covers the whole log when you want the history.
Why it matters
These three numbers are SQL Server telling you the storage did not return what it wrote. They are the most direct evidence of a hardware problem the engine can produce.
| Error | What happened | What it means |
|---|---|---|
| 823 | The operating system refused the read or write outright. | A hard I/O failure. The device, the path or the file system said no. |
| 824 | The read succeeded and the page was wrong: bad checksum, or a torn page. | Logical corruption. The data on disk is not what SQL Server wrote. |
| 825 | The read failed and then succeeded on a retry. | The warning that comes before the other two. |
825 is the one this page exists for. SQL Server retried the read up to four times, got a good result, carried on, and wrote a single informational line in the error log. No query failed. No user noticed. Nothing was raised. And storage that needs retries to return correct data is storage that will shortly stop returning correct data.
It is often called the “read retry warning” and it is routinely the only notice you get, days or weeks in advance, that a disk, a controller, a cable or a path is failing. Acting on an 825 is cheap. Acting on the 823 that follows it is a restore.
823 and 824 mean it has already happened. A page is damaged or unreadable, the affected query failed, and msdb.dbo.suspect_pages has a new row. From here the response is the corruption response: find the last clean backup, work out the scope, and fix the storage.
In every case the cause is below SQL Server. The engine is the component that noticed, not the component that failed.
How to confirm it yourself
EXEC sp_readerrorlog 0, 1, N'823';
EXEC sp_readerrorlog 0, 1, N'824';
EXEC sp_readerrorlog 0, 1, N'825';
Read the older logs too, because these often precede a restart and a restart cycles the log:
EXEC sp_enumerrorlogs;
EXEC sp_readerrorlog 1, 1, N'825';
What has been recorded permanently, which survives log cycling:
SELECT db.[name] AS [database_name],
sp.[file_id], sp.[page_id], sp.[event_type], sp.[error_count], sp.[last_update_date]
FROM msdb..suspect_pages AS sp WITH (NOLOCK)
LEFT JOIN sys.databases AS db WITH (NOLOCK) ON db.[database_id] = sp.[database_id]
ORDER BY sp.[last_update_date] DESC;
And look outside SQL Server, which is where the cause is. In the Windows system event log, events from disk, storahci, iaStorA, mpio or the HBA vendor’s driver around the same timestamps are the corroboration.
Which file and therefore which volume:
SELECT DB_NAME([database_id]) AS [database_name], [file_id], [name], [physical_name]
FROM sys.master_files WITH (NOLOCK)
WHERE [database_id] = DB_ID(N'YourDatabase');
How to fix it
Treat an 825 as urgent even though nothing has broken yet. That is the whole point of it.
- Run
DBCC CHECKDBon the affected database, and on the others on the same volume:
DBCC CHECKDB ('YourDatabase') WITH NO_INFOMSGS, ALL_ERRORMSGS;
- Check your backups are clean. Restore the most recent one somewhere else and run CHECKDB against the copy. This establishes whether you still hold a good copy, and that is the question with a deadline on it.
- Escalate to whoever owns the storage, with the timestamps and the Windows event log entries. Failing disk, degraded array, failing controller, failing cable, a path flapping in a multipath configuration: all produce this and all are fixable before they become data loss.
- For an 824, follow the corruption path, not this one. See the suspected corruption and CHECKDB errors checks. Do not restart, do not detach, and do not reach for a repair option.
- Make sure the next one reaches a person. An Agent alert on message ids 823, 824 and 825 turns this from something a scan finds into an email. That is the missing alerts check, and these three errors are the reason it matters.
Verify page checksums are actually on. An 824 can only be raised where page verification is CHECKSUM. On a database set to NONE, the same damaged page is returned silently as data, so a quiet error log is not evidence of healthy storage. That has its own check.
How long it takes
Four hours for the investigation: CHECKDB, a backup verification, and the storage conversation. Replacing hardware is separate and belongs to whoever owns it.
Related reports
| Report | Why you would go there |
|---|---|
| Error Log | The full entries rather than the last two hours. |
| Suspect Pages | What has been recorded permanently. |
| Last DBCC CheckDB Known Good by Database | Whether the data has been verified since. |
| I/O by Drive | The volume underneath, and whether it is slow as well as unreliable. |
| Backup Status | The backups you may need. |
| Disk Latency by Hour by Day | Whether the storage has been degrading for a while. |
Related checks
| Check | |
|---|---|
| Suspected Corruption | The suspect_pages side of the same event. |
| DBCC CHECKDB Corruption Errors Found | The damage found by a scheduled check. |
| Missing Alerts | Alerts on 823, 824 and 825, which is how this should reach you. |
| Page Verification set to NONE | Why an 824 might never be raised at all. |
| Slow Disk Reads | Storage that is slow, which often precedes storage that is failing. |
| Memory dumps detected | Another sign the instance has been in trouble. |
Frequently asked questions
We only have 825s and everything works. That is the best possible time to act. An 825 means the retry succeeded. The next one may not.
CHECKDB comes back clean after an 824. Possible, and the page was still wrong when it was read. Treat it as a storage warning and check the Windows event log.
Our storage team says the SAN is healthy. Give them the timestamps and the Windows event log entries. SQL Server reports what the operating system returned to it, and the fault can be anywhere in the path rather than in the array itself.
Why only two hours? So the finding is about something happening now. sp_readerrorlog and suspect_pages cover the history.