STATUS_SPARSE_NOT_ALLOWED_IN_TRANSACTION (0XC0190049) Fix
Hit this error when a file operation fails because a transaction's open on a sparse file. We'll close or commit the transaction to fix it.
You're working with a sparse file on Windows 10 or Server 2019, and you try to mark it as sparse using fsutil sparse setflag or a call to SetSparseFile in your app. Instead of success, you get error STATUS_SPARSE_NOT_ALLOWED_IN_TRANSACTION (0XC0190049). The trigger is almost always an active transaction on that file—maybe a database write, a backup job, or a volume snapshot that hasn't finalized. I know this error is infuriating because the transaction might be invisible to you. But it's simple once you track it down.
What causes this error?
Windows NTFS supports sparse files to save disk space, but the file system won't allow you to convert a regular file or modify sparse attributes while a transaction is pending on the file handle. Transactions are managed by the Kernel Transaction Manager (KTM) and often come from:
- Database engines like SQL Server or Exchange that use transactional I/O.
- Backup software using Volume Shadow Copy or file system transactions.
- Custom apps that opened the file with
FILE_FLAG_TRANSACTED.
The real fix is to either commit or roll back that transaction, or close the handle. Let's do it.
Step-by-step fix
Step 1: Identify what's locking the file
Open an elevated Command Prompt (Admin). First, run:
handle.exe -a -p "path\to\your\file.ext"
If you don't have handle.exe from Sysinternals, grab it from Microsoft's site. It shows which process has the file open and whether a transaction is active.
For a simpler check, use the built-in openedfiles query:
fsutil query openfiles | findstr "yourfile.ext"
Note the process ID (PID).
Step 2: Close the transaction (preferred method)
If you know the process (say, sqlservr.exe), you can kill or restart it. But for a surgical fix, use PowerShell to enumerate transactions:
Get-Transaction | Format-List
Check if the transaction's TransactionId matches the one locking your file. If it does, roll it back:
Undo-Transaction -InputObject (Get-Transaction -Id "your-transaction-id")
If you can't get the ID, commit or roll back all transactions:
Get-Transaction | Undo-Transaction
Be careful—this could affect other operations. Only do this on a dev or test machine first.
Step 3: Use fsutil to force close the handle
If the transaction's stuck, you can close the file handle remotely. I've had to do this on a production file server where a backup agent held a transaction open for 30 minutes.
fsutil transaction list
Output example:
| Transaction ID | State |
|---|---|
| {12345678-1234-1234-1234-123456789abc} | Active |
Now force it to roll back:
fsutil transaction commit {transaction-id}
If that fails, try:
fsutil transaction rollback {transaction-id}
Step 4: Restart the service or process
When you can't find the transaction, restarting the process holding the file kills the transaction. Use:
taskkill /F /PID 1234
Replace 1234 with the PID from Step 1. Then restart the service normally.
Step 5: Check for volume-level transactions
If the above doesn't work, the transaction might be on the volume itself—like a VSS snapshot. Run:
vssadmin list shadows
Delete any shadow copies that reference the volume:
vssadmin delete shadows /for=C: /quiet
Then try your sparse operation again.
What if it still fails?
If the error persists after closing all transactions, check these:
- File is being compressed. Sparse files and compression are mutually exclusive on NTFS. Run
compact /u "file.ext"to decompress it. - Disk is full or has quota limits. The file system may reject sparse operations if there's no room for metadata.
- Driver or filter issue. Some antivirus or backup filters intercept sparse calls. Disable any file-system filter drivers temporarily to isolate.
- Third-party transaction manager. If you use apps like SQL Server or Oracle, check their transaction logs. A long-running DDL operation could be blocking you.
This error tripped me up the first time too. Stick with the transaction hunt—it's always the culprit.
Was this solution helpful?