Skip to content

Est. 2011ยทMicrosoft Partner 7033487ยทDelivery under 3 minยทSupport 7 days a week

Your vault is empty.

License Error 948

Error 948 and 946: The Database Was Created by a Newer SQL Server Version

12 min read Updated October 4, 2026 SQL Server

Fix it now

Errors 948 and 946 mean the file or backup came from a newer build than this engine understands. 948’s published text ends with the sentence that settles it: a downgrade path is not supported. The honest choices are to open it on a version that can, or to move the data out row by row.

First tells you what you are running; second reads a backup’s header without restoring it

SELECT SERVERPROPERTY('ProductVersion') AS ThisServer, SERVERPROPERTY('ProductLevel') AS Level, SERVERPROPERTY('Edition') AS Edition;
RESTORE HEADERONLY FROM DISK = 'D:\path\file.bak';
  1. Read the two numbers in the error message. 948 states the version the database is and the highest version this server supports; 3169 does the same for a backup. Those are internal database versions, not product version numbers, so do not try to match them against 15.0 or 16.0.
  2. Establish what you are running, and whether any instance anywhere is at or above the version named.
  3. If one exists, attach or restore there first, then move the data down with a script, an export, or an insert through a linked server.
  4. If none exists, licensing and installing that version is the direct route: the file then attaches and upgrades in place during recovery.

Attaching a database to a newer instance upgrades its internal version irreversibly. Copy the files, or take a backup, before you attach anything you might need to put back.

If the database is online where you need it, you are done. If not, the next section explains why the file only moves one way.

Why it happens

Every database file records an internal version number describing the on-disk structures it uses, and an instance compares that number against what its own build understands. A newer engine knows how to read and upgrade older structures, so an older database attaches to a newer instance and is rewritten during recovery. An older engine has no knowledge of structures introduced after it shipped, so it refuses rather than guessing. 948 is that refusal for a data file and 3169 for a backup.

Microsoft’s own page for 948 names a mechanism people often miss: using an advanced feature on a newer release can raise the file’s version, so a database that nobody thinks of as having “moved” can still refuse to attach downlevel. Its example is the vardecimal storage format. The practical point is that the version in the message is a property of what was done to the database, not only of which server it last sat on.

The numbers in these messages are internal database versions and there is no Microsoft-published table mapping them to product releases. Do not try to translate them, and be wary of any list that claims to: the message already tells you the relationship you need, which is that this database is higher than this server supports. What you actually have to establish is which product version produced it, and the reliable way to do that is to ask whoever detached or backed it up, or to read the header of a backup with RESTORE HEADERONLY.

Compatibility level is a different thing entirely and is constantly confused with this. Setting it to an older value changes how the optimiser and some language features behave. It does not touch the file format and does not make the file readable by an older engine. A database restored from a newer server with its compatibility level turned down is still a newer file.

The backup was taken on a newer server

You have this one if RESTORE fails immediately with 3169 naming two database versions, and no database was ever created.

  1. Read the header first: RESTORE HEADERONLY FROM DISK = 'D:\path\file.bak'; tells you what produced it before you go looking for a server.
  2. Restore it on an instance of that version or newer.
  3. If the data has to end up on the older server, restore to the newer one first, then move it across with a script, an export, or an insert through a linked server.

There is no flag that makes an older engine accept a newer backup. 3169’s own text offers the two options: restore on a server that supports the backup, or use a backup that is compatible with this server.

The data file was detached from a newer instance

You have this one if The attach fails with 948, and 1813 appears alongside because CREATE DATABASE was aborted.

  1. Attach it on an instance of the same version or newer, then take a backup so you stop handling loose files.
  2. To land the data on the older server, script the schema and copy the rows: Generate Scripts with data included for small databases, the import and export wizard for larger ones.
  3. Recreate what the script does not carry: jobs, logins and permissions.

Scripting with data is fine for small reference databases and painful beyond a few hundred megabytes. For anything substantial, use an export or an insert through a linked server into tables you created first.

The file is not what you think it is

You have this one if 5172, where the header is rejected outright rather than a version being named.

  1. Confirm the copy finished and the file size matches the source exactly.
  2. Confirm you are attaching the data file with its matching log file, not two files from different copies.
  3. If the source instance still exists, take a backup there instead of copying files. Backups carry integrity information; loose copies do not.

5172’s published text names the property that is wrong in the header, which is worth reading: it distinguishes a truncated copy from a genuine version problem.

You are trying to move system databases across versions

You have this one if The restore that fails is of master, model or msdb, and 3168 appears naming two server versions.

  1. System database backups do not cross versions. Install the new instance at the correct version and let setup create its own.
  2. From the old server, script logins with their security identifiers preserved, then jobs, operators, linked servers and credentials.
  3. Apply those to the new instance, then restore only the user databases.

Preserving login security identifiers stops every database user being orphaned after the restore. Microsoft publishes a procedure for transferring logins and passwords between instances that does exactly this. Do it while the old server is still available.

Somebody lowered the compatibility level and expected it to help

You have this one if The database was restored to a newer server, its compatibility level was set back, and it still will not open on the old one.

  1. Accept that compatibility level and file version are unrelated. One changes query behaviour; the other is the on-disk format.
  2. Move the data rather than the file if it has to live on the older server.
  3. Set the compatibility level for the reason it exists – keeping query behaviour stable across an upgrade – not as a portability mechanism.

Full reference

Which message you have, and what it tells you

Code Published meaning What to do with it
948 The database is version N; this server supports version M and earlier; a downgrade path is not supported Find an instance at or above the version that produced it
946 Cannot open the database at that version; upgrade the database to the latest version The file needs the upgrade an older engine cannot perform
3169 The backup was taken on a server running database version N, incompatible with this server which supports version M Restore on a supporting server, or use a compatible backup
1813 Could not open new database; CREATE DATABASE is aborted The attach failed. The reason is in the message before it
3168 A system database backup was created by a different version of the server Script the objects across instead
5172 The file header is not a valid database file header; the named property is incorrect A truncated copy, a mismatched pair of files, or a version this engine cannot read

Reading a backup before you try to restore it

Header for what produced it, file list for what it contains

RESTORE HEADERONLY FROM DISK = 'D:\path\file.bak';

RESTORE FILELISTONLY FROM DISK = 'D:\path\file.bak';

RESTORE HEADERONLY returns a row per backup set on the device, including the version information that produced it and the database name. RESTORE FILELISTONLY returns the logical and physical file names, which is what you need if the target has a different drive layout. Neither touches an existing database, so both are safe to run on a production instance while you work out what you have.

Moving the data rather than the file

  1. On the newer instance, script the schema for the objects you need. Include indexes, constraints and defaults; check what your tool omits by default.
  2. Create the schema on the older instance and fix anything the older version cannot represent, which the script will tell you by failing.
  3. Move the rows: the import and export wizard for a one-off, an SSIS package for something repeatable, or an INSERT … SELECT through a linked server for moderate volumes.
  4. Recreate the objects that live outside the database: logins with their SIDs preserved, jobs, operators, linked servers and credentials.
  5. Reconcile row counts per table, then run DBCC CHECKDB on the result and take a backup.

Why there is no downgrade tool

The structures inside the file are genuinely different between releases rather than merely labelled differently, which is why 948’s published text says flatly that a downgrade path is not supported. Anything offering to rewrite a header so an older engine will open the file is proposing to hand the engine structures it does not understand, and the failure mode is corruption discovered later rather than a refusal now. Do not run such a tool against data you care about.

Avoiding this next time

  • Record the product version alongside every backup you archive. RESTORE HEADERONLY reads it back, but a note is faster.
  • Keep at least one instance at the highest version you have ever used, even if only for reads.
  • Take backups rather than copying loose .mdf and .ldf files. Backups carry integrity information and a header you can inspect.
  • Before detaching anything, check where it is going. A detach followed by a failed attach is how most of these start.

When a licence is the actual fix

When the data lives in files produced by a newer release, the only two routes are running that release or exporting the data out row by row. Licensing is usually cheaper once someone’s time is counted, and it turns a migration project into an attach that finishes during recovery. For an ordinary production instance that means SQL Server 2025 Standard (2-core pack), licensed against the cores the instance runs on, in two-core packs. Before buying anything new, check what you already hold: whether a current licence lets you run an earlier version depends on your agreement rather than on the product, so it is worth asking rather than assuming in either direction. Arco can look at what you have and tell you whether a purchase is actually needed.

Every code this article covers

Code What it points at Source
948 The database cannot be opened because its internal version is higher than this server supports; a downgrade path is not supported Microsoft Learn
946 The database cannot be opened at that version and needs upgrading to the latest version, which this engine cannot do Microsoft Learn
3169 The backup was taken on a server running a database version incompatible with this server; restore it where it is supported or use a compatible backup Microsoft Learn
1813 The new database could not be opened and CREATE DATABASE was aborted; it accompanies a failed attach Microsoft Learn
3168 A system database backup cannot be restored here because it was created by a different version of the server Microsoft Learn
5172 The file header is not a valid database file header, and the message names the property that is wrong Microsoft Learn

Confirm the fix worked

  1. The database shows ONLINE in sys.databases on the instance now hosting it.
  2. SELECT SERVERPROPERTY('ProductVersion'); on that instance is at or above the version that produced the file.
  3. Row counts on the largest tables match the source, if you moved the data rather than the file.
  4. Logins resolve to database users rather than being orphaned, if you scripted them across.
  5. Applications connect, a test write succeeds, and a fresh backup completes.

Questions people ask about this

Is there any way to downgrade a database file?

No supported one. 948’s own text says a downgrade path is not supported. The structures inside the file are genuinely different between releases, and tools claiming to rewrite headers should not be run against data you care about.

What do the version numbers in the message mean?

They are internal database versions, not product versions, and Microsoft does not publish a table mapping them to releases. Do not try to translate them. Use RESTORE HEADERONLY, or ask whoever produced the file, to find out which product version you need.

Will lowering the compatibility level help?

No. It changes optimiser and language behaviour inside a running database and has nothing to do with the on-disk format, so a newer file with a low compatibility level is still a newer file.

What is the cheapest way to get the data onto the older server?

Script the schema and copy the rows across. It costs nothing but time, and you lose anything the older version cannot represent, which you discover as the script fails. For a small database it is an afternoon; for a large one it is a project.

Do I need a full licence just to read one database once?

For a genuine one-off in a test environment, Developer edition is free and reads anything the equivalent production release can. It is licensed for development and test only, so it is no answer for anything a business process depends on.

Related error codes

Was this article helpful?

Your feedback helps us improve our documentation.

Related articles

License Error Error 40544: The Azure SQL Database Has Reached Its Size Quota Free Fix Errors 4305 and 4326: Log Backups Out of Sequence in a Restore Chain Free Fix Error 512: Subquery Returned More Than One Value, and Related Query Failures Free Fix Service Error 1069 and 17058: The SQL Server Account Cannot Start the Instance
โ† Back to Knowledge Base