Skip to content

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

Your vault is empty.

License Error 912

Error 912: Script Level Upgrade Failed After a Cumulative Update

12 min read Updated October 4, 2026 SQL Server

Fix it now

A patch replaced the binaries and the upgrade scripts then failed, so the instance takes the database offline and will not finish starting. Error 912 names the script and the inner error; 3417 reports that master could not be recovered. Start with trace flag 902, fix what the log names, then remove the flag.

Default instance. For a named instance: NET START MSSQL$INSTANCENAME /T902

NET START MSSQLSERVER /T902
  1. Read the newest instance error log first. Error 912 quotes the upgrade script that failed and the inner error number, state and severity, and the messages just before it are the real cause.
  2. Start with the upgrade scripts skipped. Either add -T902 under Startup Parameters in SQL Server Configuration Manager, or use the NET START form above, or run sqlservr.exe -s <instance> -T902 from the Binn folder.
  3. Fix what the log named. Microsoft’s documented causes for the common 574 case are conflicting user options, orphaned database users, and jobs owned by logins that no longer exist.
  4. Remove -T902 from the startup parameters and restart. The scripts run again and should complete.
  5. Confirm with SELECT SERVERPROPERTY('ProductVersion'), SERVERPROPERTY('ProductUpdateLevel'); and check the log shows the upgrade finishing.

Trace flag 902 starts new binaries against system objects that have not been upgraded. Back up master and msdb before using it, keep applications off, and remove it as soon as the blocker is cleared. Microsoft’s instruction is to remove it once the issue is resolved, not to run on it.

If the instance starts clean with no trace flag, you are done. If not, the next section explains what runs after a patch and why it stops.

Why it happens

A cumulative update replaces program files and nothing else. It cannot change the contents of your system databases while the service is stopped, so the first time the newer binaries start, the engine runs the T-SQL upgrade scripts that ship with the update. Those scripts live in the MSSQL\Install folder under the instance directory, which is why the script name in the error message looks like a filename: it is one.

The engine treats the outcome as all or nothing, because half-upgraded system objects are worse than none. Error 912’s published text says so plainly: the database will be taken offline, and if the failure was in master it will prevent the entire instance from starting. It also tells you to examine the previous error log entries, take corrective action, and restart so the scripts run to completion. Error 3417 sits alongside it and reports the failure to recover master. Setup, meanwhile, reports “Wait on Database Engine recovery handle failed” and tells you nothing useful.

Trace flag 902 skips script upgrade mode so the instance starts anyway. That gives you a connection to fix the blocker. It does not run the scripts, so the instance is in an unsupported half-patched state for as long as the flag is set.

Error 574 is the most common companion, and its cause is more specific than it looks. Microsoft’s account is that the upgrade scripts run inside a transaction, and where system objects or permissions have been modified a script can fail and leave an orphaned open transaction behind. A later script then calls sp_configure, which is a CONFIG statement, and a CONFIG statement cannot be used inside a user transaction. So 574 is a symptom of an earlier failure, not the first thing that went wrong.

574 in the log: an orphaned transaction from an earlier script

You have this one if The log shows 574, then 912 naming a script such as sqlagent100_msdb_upgrade.sql, and often 3417 after that.

  1. Start with -T902 set, then read the log for whatever failed before the 574. That is the transaction that never closed.
  2. Clear conflicting user options, which is Microsoft’s first named remedy: EXEC sp_configure 'user options', '0'; then RECONFIGURE WITH OVERRIDE;
  3. Find orphaned database users by joining sys.database_principals to sys.server_principals on SID and keeping the rows with no server principal.
  4. Find jobs whose owner no longer exists by joining msdb.dbo.sysjobs_view to master.dbo.syslogins, and reassign them.

IMPLICIT_TRANSACTIONS set through user options is the classic case. It turns ordinary statements inside the upgrade scripts into open transactions, which is exactly the state a CONFIG statement refuses to run in.

A system database log is full or its drive has no space

You have this one if A log-full or allocation error sits next to the script failure, or the volume holding the system database files is out of room.

  1. Start with -T902 set, then free space on the volume or grow the log for the database named.
  2. If the database is in full recovery, back up its log so the space becomes reusable.
  3. Remove the trace flag and restart, watching the log as the scripts run.

msdb is owned by the wrong account

You have this one if 33009 in the error log, typically after msdb was restored from another server or the sa account was renamed.

  1. With -T902 set, check ownership: SELECT name, SUSER_SNAME(owner_sid) FROM sys.databases;
  2. Correct it: ALTER AUTHORIZATION ON DATABASE::msdb TO sa; using whatever the sa account is named on this instance.
  3. Remove the trace flag and restart.

The published text of 33009 is that the owner SID recorded in master differs from the one recorded in the database, and it names ALTER AUTHORIZATION as the fix. The same mismatch causes trouble in Database Mail and Agent job ownership, so it is worth fixing even after the patch goes through.

A system database is suspect or read-only

You have this one if 926 for msdb or model, or an attach failure, appears before the script error.

  1. With -T902 set, check SELECT name, state_desc, is_read_only FROM sys.databases;
  2. Restore msdb from a recent backup if it is suspect. That is the supported route and it keeps your jobs, operators and history.
  3. Only if there is no backup, rebuild the system databases from the setup media, then restore what you can.

Rebuilding system databases discards everything held in master and msdb: logins, jobs, linked servers, credentials and history. It is the last option, not the first.

Full reference

Three documented ways to set trace flag 902

Method How
Configuration Manager SQL Server Services, right-click the instance, Properties, Startup Parameters, type -T902, Add, OK, then start the service
sqlservr.exe From the instance’s Binn folder: sqlservr.exe -s MSSQLSERVER -T902, or -s <instance name> for a named instance. Stop it with Ctrl+C then Y
NET START NET START MSSQLSERVER /T902, or NET START MSSQL$INSTANCENAME /T902

Whichever route you use, remove it the same way once the blocker is cleared. A -T902 left in the startup parameters means the upgrade scripts never run and the instance stays half patched indefinitely.

Reading the failure

What appears in the error log What it means
912 naming a script file and an inner error number That inner error is the real problem. Work on it, not on 912
3417 master could not be recovered. It accompanies 912 rather than adding information
574 A CONFIG statement ran inside a user transaction. Look further back for what opened it
33009 The database owner SID in master differs from the one in the database
926 The database is marked SUSPECT by recovery and cannot be opened
An allocation or log-full error Space, on the volume or in the log file, for the database named

Finding the two orphan cases Microsoft names

Run with -T902 set. Orphaned users first, then job owners

SELECT dp.type_desc, dp.SID, dp.name AS user_name
FROM sys.database_principals AS dp
LEFT JOIN sys.server_principals AS sp ON dp.SID = sp.SID
WHERE sp.SID IS NULL AND authentication_type_desc = 'INSTANCE';

SELECT sj.name AS Job_Name, sl.name AS Job_Owner
FROM msdb.dbo.sysjobs_view AS sj
LEFT JOIN master.dbo.syslogins AS sl ON sj.owner_sid = sl.sid
WHERE sl.name <> 'sa'
ORDER BY sj.name;

Commands worth having open

Statement or place What it gives you
Startup Parameters in Configuration Manager Where -T902 is added and, more importantly, removed
SELECT SERVERPROPERTY('ProductVersion'), SERVERPROPERTY('ProductUpdateLevel'); The build and update level actually running
SELECT name, state_desc, is_read_only, SUSER_SNAME(owner_sid) FROM sys.databases; State and ownership of every system database in one look
ALTER AUTHORIZATION ON DATABASE::msdb TO sa; Corrects an msdb owner mismatch
EXEC sp_configure 'user options'; Whether something like IMPLICIT_TRANSACTIONS is set instance-wide
<instance directory>\MSSQL\Install The upgrade scripts themselves, named in the 912 message

Other inner errors Microsoft documents for this failure

Microsoft maintains a set of articles for specific upgrade-script failures, each keyed on the inner error rather than on 912. Among them are 574 for the CONFIG statement case, 945 where SSISDB is part of an availability group, 1712 for online index operations on a lower edition, 2714 for an object that already exists, 4860 for a missing file, 5133 where the temporary database could not be created, 15151 and 15173 for principal problems, and 17182 where TLS 1.0 has been disabled. If the inner error in your log is one of those, search for it directly rather than reading general 912 advice.

What not to do

  • Do not uninstall the update. Removing it will not undo scripts that already ran, and it leaves you unpatched with the original problem intact.
  • Do not leave -T902 set and carry on. The instance is running new binaries against un-upgraded system objects, which is not a supported state.
  • Do not restore master from a different server to ‘fix’ ownership. Correct the owner with ALTER AUTHORIZATION instead.
  • Do not skip the backups. You are about to work on master and msdb, so back them up before you change anything.

When a licence is the actual fix

Nothing in this article costs money. Trace flag 902, the log reading and every remedy above are free, and the fix is almost always a system object somebody changed years ago. A licence becomes the answer only in one situation: the build you are patching no longer receives cumulative updates, so there is no update to apply and no supported way forward on it. Moving to a serviced release is a purchase rather than a repair, typically SQL Server 2025 Standard (2-core pack) for an ordinary production instance, licensed against the cores that instance runs on. Arco can check whether your build is still serviced before you spend anything, and size the core count if it is not.

Every code this article covers

Code What it points at Source
912 A script level upgrade for a system database failed at a named step, so the database is taken offline; if it was master, the instance will not start Microsoft Learn
574 A CONFIG statement was run inside a user transaction, typically an sp_configure call caught in a transaction an earlier failed upgrade step left open Microsoft Learn
33009 The database owner SID recorded in master differs from the one recorded in the database itself Microsoft Learn
926 The database cannot be opened because recovery marked it SUSPECT; the error log carries the reason Microsoft Learn

Confirm the fix worked

  1. The service starts with no trace flag in the startup parameters and stays running.
  2. The error log for that clean start shows the script upgrade completing, followed by the ready for connections entry, and no 912 or 3417.
  3. SERVERPROPERTY('ProductVersion') matches the build you installed and ProductUpdateLevel shows the update.
  4. SELECT name, state_desc FROM sys.databases; shows every system database ONLINE.
  5. SQL Server Agent starts and a test job runs to completion.

Questions people ask about this

Can I just uninstall the update?

Removing an update is possible but it will not undo scripts that already ran, and it leaves you unpatched with the original blocker still in place. Clearing the blocker and letting the scripts finish is both faster and supported.

Are my user databases at risk?

Upgrade scripts change system objects in master and msdb, not your data, and your databases were not opened during the failed startup. Back them up anyway, because you are about to work on master and msdb.

How long can I safely run with -T902 set?

Microsoft’s instruction is to remove it once the underlying issue is resolved, so that setup can restart the upgrade script phase. It is a door to get in through, not a running configuration, and some behaviour will be odd while it is set.

Why does setup say ‘Wait on Database Engine recovery handle failed’ instead of anything useful?

Because that is all setup can see. The scripts run inside the engine after the binaries are replaced, so when they fail setup only knows the instance did not come up. Errors 912 and 3417 in the instance error log are the real report.

Do I need to buy anything?

Not for the fixes here, which are all free. The only licensing question arises if the build you are on is no longer serviced, in which case moving to a supported version is a purchase rather than a repair.

Related error codes

Was this article helpful?

Your feedback helps us improve our documentation.

Related articles

Free Fix Error 22050: Database Mail Fails to Format or Send the Query Results Free Fix Error 10061 and 10060: TCP Connection Refused or Timed Out to SQL Server License Error Error 18401 and 17187: SQL Server Is Not Ready to Accept Connections License Error Error 18752: Only One Log Reader Agent Can Connect to the Database
โ† Back to Knowledge Base