- Error number
- 3117
- Severity
- 16 (user-correctable error)
- State
- 1
- Product
- Microsoft SQL Server Database Engine
- Versions
- All supported SQL Server versions (2016 to 2025), Azure SQL Managed Instance
- Category
- Backup & Restore
- Last reviewed
- 24 October 2026
On this page
What it means
Error 3117 means you tried to apply a log or differential backup to a database that has already been recovered (or was never restored), so it is no longer waiting for more backups.
A restore sequence has two phases. While backups are applied WITH NORECOVERY, the database stays in the RESTORING state and is "ready to roll forward": the next differential or log backup can be added. Recovery (WITH RECOVERY, which is the default when you specify neither) rolls back unfinished transactions and opens the database. From that moment it has a new history, and further log or differential backups from the old one cannot be applied. Trying anyway raises 3117, followed by Msg 3013 naming RESTORE LOG or RESTORE DATABASE.
So the message almost always means that an earlier step in your script recovered the database too soon: a RESTORE DATABASE without any recovery option, the SSMS restore dialog left on "RESTORE WITH RECOVERY", or a stray RESTORE DATABASE ... WITH RECOVERY. The failed statement changes nothing. To add the remaining backups you have to restart the sequence from the full backup, this time with NORECOVERY on every step except the last.
Common causes
- The full backup was restored without NORECOVERY. RESTORE defaults to WITH RECOVERY, so the database was opened straight away.
- The differential, or an earlier log backup, was restored WITH RECOVERY (or with no option) before the remaining log backups.
- In the SSMS restore dialog the recovery state was left at RESTORE WITH RECOVERY while restoring the files one at a time.
- A log shipping secondary or a standby copy was brought online (recovered), and the restore job then tries to apply the next log backup to it.
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.
Is the database still waiting for backups?
SELECT name, state_desc, is_in_standby, recovery_model_desc
FROM sys.databases
WHERE name = N'AppDb'; RESTORING (or is_in_standby = 1) means more backups can be applied. ONLINE means the database has been recovered and 3117 is expected for any further log or differential backup.
Which restore step recovered the database?
msdb.dbo.restorehistory records every restore with its options. restore_type is D (database), I (differential) or L (log).
SELECT TOP (10) rh.restore_date, rh.restore_type, rh.recovery, rh.[replace],
bs.backup_finish_date, mf.physical_device_name
FROM msdb.dbo.restorehistory AS rh
JOIN msdb.dbo.backupset AS bs ON bs.backup_set_id = rh.backup_set_id
JOIN msdb.dbo.backupmediafamily AS mf ON mf.media_set_id = bs.media_set_id
WHERE rh.destination_database_name = N'AppDb'
ORDER BY rh.restore_history_id DESC; The most recent row with recovery = 1 is the step that ended the sequence. Everything you wanted to apply after it has to be redone from the full backup.
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.
Restart the sequence with NORECOVERY on every step but the last
Changes database stateRestore the full backup again WITH NORECOVERY, then the latest differential (if any), then each log backup taken after it, all WITH NORECOVERY. Finish with WITH RECOVERY on the last file, or run RESTORE DATABASE AppDb WITH RECOVERY; on its own once you are sure nothing else needs applying.
Caution: REPLACE overwrites the database you just recovered, including any changes made in it since. If users or jobs have already written to it, take a backup of it first.
USE master;
RESTORE DATABASE AppDb
FROM DISK = N'D:\Backups\AppDb_full.bak'
WITH REPLACE, NORECOVERY;
RESTORE DATABASE AppDb
FROM DISK = N'D:\Backups\AppDb_diff.bak'
WITH NORECOVERY;
RESTORE LOG AppDb
FROM DISK = N'D:\Backups\AppDb_log_1100.trn'
WITH NORECOVERY;
RESTORE LOG AppDb
FROM DISK = N'D:\Backups\AppDb_log_1200.trn'
WITH RECOVERY;
Need to look at the data between steps? Use STANDBY
Changes database stateWITH STANDBY opens the database read-only between restores but keeps it ready to roll forward, so you can check the data and still apply the next log backup. SQL Server keeps the undo information in the standby file you name; it must be on a path the service account can write to.
RESTORE LOG AppDb
FROM DISK = N'D:\Backups\AppDb_log_1100.trn'
WITH STANDBY = N'D:\Backups\AppDb_undo.tuf';
Script restores explicitly instead of relying on defaults
Client or network sideWrite NORECOVERY or RECOVERY on every RESTORE statement in runbooks and generated scripts, so the default can never end a sequence by accident. In the SSMS restore dialog, select all the backup files in one go and let it choose the recovery state for each step, or set "RESTORE WITH NORECOVERY" when you restore them one at a time.
Examples
Restoring a log backup after a full restore WITH RECOVERY (the default)
Throwaway database; the backups go to the instance default backup folder. The RESTORE DATABASE has no recovery option, so it recovers the database.
-- Throwaway database in FULL recovery: a full backup and a log backup
ALTER DATABASE AppDb SET RECOVERY FULL;
DECLARE @p nvarchar(200) = CAST(SERVERPROPERTY('InstanceDefaultBackupPath') AS nvarchar(200));
DECLARE @full nvarchar(260) = @p + N'\cws_errlab_3117.bak',
@log nvarchar(260) = @p + N'\cws_errlab_3117.trn';
BACKUP DATABASE AppDb TO DISK = @full WITH INIT;
CREATE TABLE dbo.Orders (id int PRIMARY KEY);
INSERT dbo.Orders VALUES (1);
BACKUP LOG AppDb TO DISK = @log WITH INIT;
USE master;
RESTORE DATABASE AppDb FROM DISK = @full WITH REPLACE; -- recovers: RECOVERY is the default
RESTORE LOG AppDb FROM DISK = @log;
Msg 3117, Level 16, State 1, Line 13 The log or differential backup cannot be restored because no files are ready to rollforward. Msg 3013, Level 16, State 1, Line 13 RESTORE LOG is terminating abnormally.
Reproduced on SQL Server 2025 (17.0.1145.4), 23 October 2026.
Restoring a differential after the full backup was recovered
Same throwaway setup with a differential backup. The follow-up message names RESTORE DATABASE, because a differential is restored with RESTORE DATABASE.
ALTER DATABASE AppDb SET RECOVERY FULL;
DECLARE @p nvarchar(200) = CAST(SERVERPROPERTY('InstanceDefaultBackupPath') AS nvarchar(200));
DECLARE @full nvarchar(260) = @p + N'\cws_errlab_3117.bak',
@diff nvarchar(260) = @p + N'\cws_errlab_3117_diff.bak';
BACKUP DATABASE AppDb TO DISK = @full WITH INIT;
CREATE TABLE dbo.Orders (id int PRIMARY KEY);
BACKUP DATABASE AppDb TO DISK = @diff WITH INIT, DIFFERENTIAL;
USE master;
RESTORE DATABASE AppDb FROM DISK = @full WITH REPLACE, RECOVERY;
RESTORE DATABASE AppDb FROM DISK = @diff;
Msg 3117, Level 16, State 1, Line 11 The log or differential backup cannot be restored because no files are ready to rollforward. Msg 3013, Level 16, State 1, Line 11 RESTORE DATABASE is terminating abnormally.
Reproduced on SQL Server 2025 (17.0.1145.4), 23 October 2026.
How to prevent it
Treat NORECOVERY as the normal option during a restore and RECOVERY as the deliberate last step. Generate restore scripts from msdb backup history (or your backup tool) so that the recovery option is set correctly for each file, and review the last line before running them.
Practise the full restore sequence on a test server, including a differential and several log backups. The first time you discover that the default is WITH RECOVERY should not be during an outage.
Common questions
Can I undo WITH RECOVERY and continue applying log backups?
No. Once recovered, the database cannot go back to the restoring state of that sequence. Restore the full backup again WITH NORECOVERY and reapply the backups.
Why is "rollforward" written as one word?
That is the engine's own wording in sys.messages. Search for the message exactly as SQL Server prints it.
How do I finish a restore if the last file was restored WITH NORECOVERY?
Run RESTORE DATABASE AppDb WITH RECOVERY; without a FROM clause. It recovers the database using what has already been restored.
Learn more on CodeWithSQL
Official documentation
- RESTORE statements: arguments (Transact-SQL)
- Restore and recovery overview (SQL Server)
- Apply transaction log backups (SQL Server)
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.