Skip to content
Microsoft SQL Server

SQL Server Error 3203

Read on the backup device failed

Severity 16 Backup & Restore
Applies to: All supported SQL Server versions (2016 to 2025), Azure SQL Managed Instance
Last technically reviewed 24 October 2026 on SQL Server 2025 (17.0.1145.4)
The full message
Read on "D:\Backups\AppDb.bak" failed: 38(Reached the end of the file.)
Other forms of this message
Data in the file is not what SQL Server expects
Read on "D:\Backups\AppDb.bak" failed: 13(The data is invalid.)
Storage reported a read error
Read on "D:\Backups\AppDb.bak" failed: 23(Data error (cyclic redundancy check).)
Read on "\\fileserver\Backups\AppDb.bak" failed: 1117(The request could not be performed because of an I/O device error.)
Followed by (RESTORE DATABASE; the verb matches the statement)
RESTORE DATABASE is terminating abnormally.
Error number
3203
Severity
16 (user-correctable error)
State
Not documented by Microsoft (not reproduced here)
Product
Microsoft SQL Server Database Engine
Versions
All supported SQL Server versions (2016 to 2025), Azure SQL Managed Instance
Last reviewed
24 October 2026

What it means

Error 3203 means SQL Server opened the backup file but could not read all of it, usually because the file is incomplete, damaged in transit or stored on failing media.

The message has two parts. The quoted text is the backup device (file path, share or URL) that SQL Server was reading, and after failed: comes the Windows error number and its text. That second part tells you which problem you have: 38 (Reached the end of the file) means the file is shorter than the backup it describes, typically an unfinished copy or download; 13 (The data is invalid) means the bytes are not what the backup format expects; 23 or 1117 are read errors from the disk, controller or network path.

Unlike error 3201, the file was found and opened, so the path and permissions are fine. Unlike error 3241, which is about a file that is not a valid backup at all, 3203 happens while reading the data. The statement then ends with error 3013. The catalogue severity is 16; the state is not documented by Microsoft.

Common causes

  • The backup file was copied, uploaded or downloaded only partly (an interrupted copy, a full disk at the destination, a size limit on the transfer), so it ends early (error 38).
  • The file was altered in transit, for example by an FTP transfer in text (ASCII) mode or by a tool that rewrites line endings (error 13).
  • The disk, storage array, USB drive or network share holding the backup returns read errors (errors 23 or 1117).
  • The backup was written to failing media in the first place; without WITH CHECKSUM on the backup this goes unnoticed until the restore.
  • Restoring from a file that another process is still writing, such as a backup or copy that has not finished yet.

Diagnose it

Read-only These queries only read metadata and dynamic management views. They do not change data, permissions or configuration, so they are safe to run first.

How big should the backup be?

For a backup taken on this server, msdb records its size and whether it has checksums. Compare the size with the file you are restoring from. For a file from elsewhere, compare with the size at the source.

SELECT TOP (20) bs.database_name, bs.backup_finish_date, bs.type,
       bs.backup_size, bs.compressed_backup_size,
       bs.has_backup_checksums, bs.is_damaged, mf.physical_device_name
FROM msdb.dbo.backupset AS bs
JOIN msdb.dbo.backupmediafamily AS mf ON mf.media_set_id = bs.media_set_id
ORDER BY bs.backup_finish_date DESC;
What to look for

The file on disk should be at least compressed_backup_size bytes. is_damaged = 1 means the backup was already known to be damaged, and has_backup_checksums = 0 means it was never verified when written.

How big is the file SQL Server sees?

Lists backup files and their sizes as the SQL Server service account sees them. Replace the folder with the one from the message.

DECLARE @folder nvarchar(4000) = CAST(SERVERPROPERTY('InstanceDefaultBackupPath') AS nvarchar(4000));
SELECT full_filesystem_path, size_in_bytes, last_write_time
FROM sys.dm_os_enumerate_filesystem(@folder, N'*.bak');
What to look for

A file much smaller than the expected size, or with a last_write_time that is still changing, confirms an incomplete copy.

Find backup I/O errors in the error log

EXEC sp_readerrorlog 0, 1, N'BackupIoRequest';
EXEC sp_readerrorlog 0, 1, N'3203';
What to look for

Entries naming the backup device and the operating system error. Several failures on the same drive or share point to the storage rather than to one file.

How to fix it

Each fix is labelled with what it changes. Try read-only checks and the least invasive fix first, and test changes outside production.

Get a complete copy of the backup and verify it

Read-only

Copy the file again from its source in binary mode, compare its size (and a hash such as Get-FileHash in PowerShell) with the original, then check it without restoring: RESTORE VERIFYONLY FROM DISK = N'D:\Backups\AppDb.bak' WITH CHECKSUM; reads the whole backup and, when the backup has them, also checks page and backup checksums. It creates no database.

Take a new backup if the source database is still available

Changes database state

If the database is still online somewhere, a fresh backup with checksums is quicker than recovering a damaged file. COPY_ONLY keeps the regular backup chain unchanged.

BACKUP DATABASE AppDb
TO DISK = N'D:\Backups\AppDb_copy.bak'
WITH COPY_ONLY, CHECKSUM, COMPRESSION;

RESTORE VERIFYONLY FROM DISK = N'D:\Backups\AppDb_copy.bak' WITH CHECKSUM;

Check the storage or network path

Client or network side

For errors 23 and 1117, look in the Windows System event log for disk, controller or network errors at the time of the restore, and copy the file to local, healthy storage before restoring. Keep backups on more than one device so a single failing disk does not cost you the only copy.

Last resort: restore what can be read, under a new name

Changes database state

When no other copy exists, CONTINUE_AFTER_ERROR makes RESTORE carry on past damaged parts of the backup. Restore under a new name, then run DBCC CHECKDB and copy out what you need.

Caution: The resulting database can be inconsistent or incomplete. Never restore this way over the existing database, and treat the result as salvage, not as a recovered production database.

RESTORE DATABASE AppDb_Salvage
FROM DISK = N'D:\Backups\AppDb.bak'
WITH CONTINUE_AFTER_ERROR,
     MOVE N'AppDb'     TO N'D:\SQLData\AppDb_Salvage.mdf',
     MOVE N'AppDb_log' TO N'D:\SQLLogs\AppDb_Salvage_log.ldf';

Examples

Restoring from a backup copy that ended early

Shown as documented, not reproduced here: it needs a truncated or damaged backup file. The text after failed: depends on the operating system error; the state is not documented by Microsoft, so no header is shown.

RESTORE DATABASE AppDb
FROM DISK = N'D:\Backups\AppDb.bak'   -- copied from another server, copy was interrupted
WITH REPLACE;
Result
Read on "D:\Backups\AppDb.bak" failed: 38(Reached the end of the file.)
RESTORE DATABASE is terminating abnormally.

How to prevent it

Back up WITH CHECKSUM, and verify every copy you rely on with RESTORE VERIFYONLY ... WITH CHECKSUM after it reaches its final location, not only where it was written. When moving backups between servers, compare file sizes or hashes before deleting the source.

Test restores regularly on another server. A restore that has worked recently is the only real proof that a backup file is readable end to end.

Common questions

Does error 3203 mean my database is corrupt?

Not necessarily. It means the backup file could not be read. The database the backup came from may be fine, in which case a new backup is the easiest fix.

Why does RESTORE HEADERONLY work but RESTORE DATABASE fails?

HEADERONLY reads only the beginning of the file. A file cut off later in the copy has a valid header, so the error appears only when the full restore reads past the end.

What does operating system error 38 mean in a restore?

Reached the end of the file: the file is shorter than the backup it describes. Copy it again from the source and compare sizes.

Learn more on CodeWithSQL

Official documentation

Last technically reviewed 24 October 2026; examples and diagnostics run on SQL Server 2025 (17.0.1145.4). Message text checked against the engine's sys.messages catalogue.

Still stuck on a SQL Server error?

Browse the full SQL Server error library, or get hands-on help from an experienced SQL professional.