Fix it now
RESTORE has noticed that the database already on the target is not the one in the backup set, and it refuses to overwrite until you say plainly that you meant to. That check compares the database family GUID recorded in the backup with the one on the server, so it is not fooled by a matching name. WITH REPLACE removes the objection and MOVE handles the file layout.
SELECT @@SERVERNAME, DB_NAME();
RESTORE HEADERONLY FROM DISK = N'D:\bk\Source.bak';
RESTORE FILELISTONLY FROM DISK = N'D:\bk\Source.bak';
- Check you are on the instance you think you are. A production database and last week’s test copy have very similar names at three in the morning.
- If the target holds anything you might want later, back it up first. REPLACE destroys it and there is no undo.
- Take exclusive access:
ALTER DATABASE [Target] SET SINGLE_USER WITH ROLLBACK IMMEDIATE; - Restore with REPLACE and one MOVE clause per logical file from the FILELISTONLY output.
- Return it to service:
ALTER DATABASE [Target] SET MULTI_USER;
REPLACE also skips the tail-log backup requirement. On a database in full or bulk-logged recovery that means losing every transaction since the last log backup, silently.
If the restore completes and the application reads its data, you are done. If it is still refused, the next section covers what each of the five codes is asking for.
Why it happens
A backup set records the identity of the database it came from, not merely its name. When you restore into an existing database, SQL Server compares the database family GUID in the backup set with the one recorded on the server, and if they differ the database is not restored. Microsoft calls this an important safeguard, and it is: it is the thing standing between a tired administrator and an overwritten production database.
REPLACE tells the restore to proceed anyway, and Microsoft is unusually direct about what that costs. It documents three separate protections that REPLACE removes. First, you may overwrite an existing database with whatever database is in the backup set, even where the names differ. Second, on a database in full or bulk-logged recovery you may restore without a tail-log backup, which loses the most recently written log. Third, you may overwrite existing files of the wrong type entirely, including files belonging to another database that happens to be offline. Its own guidance is that REPLACE should be used rarely and only after careful consideration.
MOVE handles the other half of the problem. The backup remembers the paths the files had on the original server, and those paths may not exist here. Each logical file needs a MOVE clause pointing somewhere valid on this machine, and the logical names come from RESTORE FILELISTONLY rather than from guesswork. 3234 is the error you get when a name in a MOVE clause is not one of the names in the backup, and its own message tells you to run FILELISTONLY.
You are deliberately restoring over a differently named database
You have this one if 3154 or 3141, and you know the target is a copy or a test database you intend to refresh.
- Back up the target first if it holds anything unique.
- Take exclusive access with SINGLE_USER as above.
- Restore with REPLACE and one MOVE clause per logical file.
- Return to MULTI_USER and re-check permissions, because database users and server logins do not always line up after a cross-server restore.
ALTER DATABASE [Target] SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
RESTORE DATABASE [Target]
FROM DISK = N'D:\bk\Source.bak'
WITH REPLACE,
MOVE N'Source' TO N'E:\Data\Target.mdf',
MOVE N'Source_log' TO N'F:\Log\Target_log.ldf',
RECOVERY;
ALTER DATABASE [Target] SET MULTI_USER;
Logical file names come from FILELISTONLY and stay as they were in the source database. They do not have to match the new database name, and renaming them is a separate operation.
The target server has a different drive layout
You have this one if The restore complains about a path, or 3234 appears because a MOVE clause names something not in the backup.
- Run
RESTORE FILELISTONLY FROM DISK = N'<path>';and copy the LogicalName values exactly. - Write one MOVE clause per row returned, pointing at folders that exist on this server.
- Include every file, not only the data and log files. Full-text, FILESTREAM and secondary data files each need their own clause.
- Confirm the service account can write to the destination folders before starting a long restore.
Something is connected to the target database
You have this one if 3101, and the restore fails immediately without touching the files.
- Switch your own query window to master first:
USE master;A connection in the target database blocks its own restore. - Set single-user mode with rollback:
ALTER DATABASE [Target] SET SINGLE_USER WITH ROLLBACK IMMEDIATE; - If connections keep reappearing, stop the application or disable its logins for the duration.
- Set MULTI_USER afterwards. A database left in single-user mode locks out everyone but whichever session gets in first.
The target is in an availability group, mirroring or log shipping
You have this one if The restore is refused on a database that belongs to a high availability configuration.
- Remove the database from the availability group, or break the mirroring or log shipping relationship, before restoring.
- Restore on the primary, then re-add the database and reseed the secondaries.
- Confirm the configuration afterwards rather than assuming it reconnected on its own.
The device is not the backup you assumed
You have this one if 3143, or HEADERONLY shows a different database name or an unexpected backup date.
- Run
RESTORE HEADERONLY FROM DISK = N'<path>';and check the DatabaseName, BackupFinishDate and Position columns. - If the file holds several backup sets, name the one you want:
RESTORE DATABASE [Target] FROM DISK = N'<path>' WITH FILE = 2, ... - Cross-check against the source instance’s history in
msdb.dbo.backupsetto be sure you have the right file.
3143’s own message says the data set on the device is not a SQL Server backup set. If HEADERONLY fails too, this is a media problem rather than a target problem.
Full reference
Which error you have, and what it wants
| Error | What the restore is asking for |
|---|---|
| 3154 | Confirmation that overwriting this target is intended. The backup set holds a backup of a database other than the existing one |
| 3141 | The same, named from the backup’s point of view: the database to be restored was named X, reissue with WITH REPLACE to overwrite Y |
| 3234 | A MOVE clause naming a logical file that is actually part of this backup. The message tells you to run RESTORE FILELISTONLY |
| 3101 | Exclusive access. Something, possibly your own query window, is connected to the target |
| 3143 | A device that holds a SQL Server backup set at all. This one does not |
What REPLACE switches off
| Safeguard removed | What can go wrong |
|---|---|
| The database family GUID check | You overwrite an existing database with a backup of a different database, even where the names differ |
| The tail-log backup requirement | On full or bulk-logged recovery, you lose every transaction written since the last log backup |
| The existing-file check | You overwrite files of the wrong type, or files belonging to another database that is offline |
Microsoft’s stated rule is that for a database in full or bulk-logged recovery you must in most cases back up the tail of the log before restoring over it, unless the RESTORE statement carries WITH REPLACE or WITH STOPAT. That is worth reading twice: REPLACE is not only a naming override, it is also the switch that lets you discard the tail of the log without being asked.
The safer habit
Restore to a new database name with MOVE clauses pointing at new file paths. Nothing about the original is touched, you keep a working copy while you check the restored one, and the whole class of REPLACE accidents becomes impossible. It costs disk space and nothing else. Where the target genuinely must be overwritten, back it up first even when you are confident, because the cost of that backup is minutes and the cost of being wrong is the database.
After a cross-server restore
- Confirm the database is online and in the recovery model you expect:
SELECT name, state_desc, recovery_model_desc FROM sys.databases WHERE name = N'Target'; - Confirm the files landed where you intended:
SELECT name, physical_name FROM sys.master_files WHERE database_id = DB_ID(N'Target'); - Fix orphaned database users. A database user whose SID does not match any login on this instance cannot be used, and the application will report a permissions problem rather than a restore problem.
- Re-create anything that lived outside the database: SQL Agent jobs, linked servers, server-level permissions, credentials.
- Take a fresh full backup, so the restored database has a chain of its own.
Reading HEADERONLY properly
When a file holds several backup sets, Position is the column that matters, and WITH FILE = <position> is how you select one. DatabaseName and BackupFinishDate together tell you whether this is the file you meant; a mismatch there is the cheapest possible moment to find out. If you are restoring from a file you did not create, read HEADERONLY before anything else, every time.
Every code this article covers
| Code | What it points at | Source |
|---|---|---|
3154 |
The backup set holds a backup of a database other than the existing database on the target | Microsoft Learn |
3141 |
The database to be restored was named differently. Reissue the statement using the WITH REPLACE option to overwrite the existing database | Microsoft Learn |
3234 |
The logical file named in a MOVE clause is not part of this database. Use RESTORE FILELISTONLY to list the logical file names | Microsoft Learn |
3101 |
Exclusive access could not be obtained because the database is in use | Microsoft Learn |
3143 |
The data set on the device is not a SQL Server backup set | Microsoft Learn |
Confirm the fix worked
- Confirm the database is online:
SELECT name, state_desc, recovery_model_desc FROM sys.databases WHERE name = N'Target'; - Confirm the files landed where you intended:
SELECT name, physical_name FROM sys.master_files WHERE database_id = DB_ID(N'Target'); - Check the restore history:
SELECT TOP 5 destination_database_name, restore_date FROM msdb.dbo.restorehistory ORDER BY restore_date DESC; - Have the application connect and read a known row, and fix orphaned database users if logins do not match.
- Take a fresh full backup of the restored database so it has its own chain.
Questions people ask about this
Does any of this need a particular edition or extra licence?
No. Restoring, REPLACE and MOVE are core features in every edition, including the free ones. The only edition rule that bites is the reverse case: a database using features your target edition does not offer will not restore onto it.
Is WITH REPLACE dangerous?
It is as dangerous as what it overwrites, and it removes more than one safeguard. Microsoft documents three: the check that the backup belongs to this database, the requirement for a tail-log backup, and the check on overwriting existing files. Confirm the target and the instance before you type it, and back the target up if there is any doubt.
Can I restore a database under a new name without affecting the original?
Yes, and it is the safer habit. Restore to a new database name with MOVE clauses pointing at new file paths. Nothing about the original is touched.
Why does it refuse even though the database names match?
Because the check is on the database family GUID recorded in the backup set, not on the name. A database dropped and recreated with the same name is a different database as far as RESTORE is concerned, and that is deliberate.
Why did my restore leave the database in Restoring state?
Because the last statement used NORECOVERY, which is correct while you still have log backups to apply. Finish with RESTORE DATABASE [Target] WITH RECOVERY; once the final file is in.
