Applies to SQL Server 2019, 2022 and 2025.
SQL Server audit failures happen when the instance can’t write audit records to the target: the disk is full, the share has gone, or the service account has lost its permissions on the folder. What happens next is decided by one setting on the server audit, ON_FAILURE. I think it’s the most important line in any audit definition, and it’s usually the one nobody has thought about.
The three ON_FAILURE options for SQL Server audit failures
- CONTINUE (the default). Work carries on as normal. The audit records that can’t be written are lost. SQL Server keeps trying and picks up again once the target is writable.
- FAIL_OPERATION. Any action that would create an audited event fails. Actions that aren’t audited carry on. The instance stays up, and the audit resumes once the problem is fixed.
- SHUTDOWN. The instance stops if it can’t write to the target for any reason. The login that creates the audit needs the SHUTDOWN permission, or the CREATE SERVER AUDIT statement fails.
So the choice is really about what matters more to the business: keeping the database available, or never having a gap in the audit trail. CONTINUE favours availability. SHUTDOWN favours the audit trail at any cost. FAIL_OPERATION sits in between: only the audited work stops.
Checking and changing the setting
This shows each server audit, its failure option and whether it’s actually running right now:
SELECT a.name AS AuditName,
a.on_failure_desc AS OnFailure,
a.queue_delay AS QueueDelayMs,
a.is_state_enabled,
s.status_desc AS CurrentStatus,
s.status_time AS StatusChangedUtc,
s.audit_file_path AS CurrentFile
FROM sys.server_audits AS a
LEFT JOIN sys.dm_server_audit_status AS s
ON s.audit_id = a.audit_id
ORDER BY a.name;
The status column is the one to watch. STARTED is good. RUNTIME_FAIL means the audit is enabled but isn’t writing, and TARGET_CREATION_FAILED means it never managed to open the target. I use a LEFT JOIN so an audit still shows up even if the DMV has no status row for it.
To change the option you have to switch the audit off first. ALTER SERVER AUDIT won’t change anything else while the audit is on, and it can’t run inside a user transaction:
USE master;
ALTER SERVER AUDIT [DBA_Audit] WITH (STATE = OFF);
ALTER SERVER AUDIT [DBA_Audit] WITH (ON_FAILURE = FAIL_OPERATION);
ALTER SERVER AUDIT [DBA_Audit] WITH (STATE = ON);
The audit specifications attached to it stay as they are; you don’t need to recreate them.
The common mistake: CONTINUE with nobody watching
Most audits I inherit use CONTINUE, because it’s the default and because nobody wants the audit to cause an outage. That’s a reasonable choice. The mistake is assuming that someone will notice when it fails. With CONTINUE, there’s no error for users or applications. Queries run, the audit status quietly changes to RUNTIME_FAIL, and records are simply dropped until the target comes back. Months later an auditor asks for last March and there’s a hole in it.
The opposite mistake is choosing SHUTDOWN because a policy document says “the audit must be complete”, then putting the audit files on a volume that fills up. Now a full disk is a full outage, and the instance may not even start, because the audit fails again during startup.
Whichever option you choose, the fix is the same: size the target properly (MAXSIZE and MAX_ROLLOVER_FILES, with room to spare) and monitor it. I run the query above from a SQL Server Agent job every few minutes and raise an alert for any enabled audit whose status isn’t STARTED. That turns a silent gap into a ticket.
Getting back in after a SHUTDOWN audit failure
If an audit with ON_FAILURE = SHUTDOWN has stopped the instance, fix the target first (free the space, restore the share or the folder permissions). If you can’t, start the instance in single-user mode with the -m startup option. In that session, SHUTDOWN audits behave as if they were set to CONTINUE, and SQL Server notes the bypass in the error log, so you can log in and switch the audit off or move its target. If the failure happens while the audit is starting up and the instance won’t start at all, Microsoft’s documentation points you to the -f (minimal configuration) startup option.
Watch out for
- CONTINUE is the default. If you didn’t specify ON_FAILURE, that’s what you have, and failures are silent.
- FAIL_OPERATION makes audited actions fail with an error, so applications that touch audited tables will see errors while the target is broken.
- SHUTDOWN needs the SHUTDOWN permission when the audit is created, and keeps working even if that permission is later revoked.
- QUEUE_DELAY = 0 makes delivery synchronous. It doesn’t change what ON_FAILURE does when the target fails, and it costs performance on busy systems.
- The audit must be STATE = OFF before you can change ON_FAILURE or the target.
- Audit specifications can be changed while the audit is running; the audit itself can’t.
For the basics of setting up a server audit and its specifications, see my SQL Server Audit post, and for more notes like this, the SQL Server DBA Handbook. Microsoft’s reference for the options is CREATE SERVER AUDIT (Transact-SQL), and the startup recovery steps are in SQL Server Audit (Database Engine).
This topic came up in the SQLServerCentral Question of the Day: SQL Server Audit Failures.
Clive Roberts DBA