How to fix SQLITE_IOERR_FSYNC: Error during fsync() in SQLite

SQLiteADVANCEDCRITICALUpdated Dec 22, 2025· 259 views

SQLite failed to flush buffered data to persistent storage via the fsync() system call. This extended I/O error (code 1034) occurs when the operating system cannot sync written data to disk.

Quick fix

Fixes SQLITE_IOERR_FSYNC

#include <sqlite3.h>

void error_log_callback(void *pArg, int iErrCode, const char *zMsg) {
    fprintf(stderr, "SQLite Error [%d]: %s\n", iErrCode, zMsg);
}

// During initialization
sqlite3_config(SQLITE_CONFIG_LOG, error_log_callback, NULL);
  1. Enable SQLite logging to identify the affected file
  2. Check filesystem health and repair if needed
  3. Test storage hardware for failures
  4. Verify filesystem mount options and permissions
sqlite — error
#include <sqlite3.h>
void error_log_callback(void *pArg, int iErrCode, const char *zMsg) {
fprintf(stderr, "SQLite Error [%d]: %s\n", iErrCode, zMsg);
}
// During initialization
sqlite3_config(SQLITE_CONFIG_LOG, error_log_callback, NULL);
SQLITE_IOERR_FSYNC: Error during fsync()

What this error means

SQLITE_IOERR_FSYNC is an extended error code (1034) that indicates SQLite encountered an I/O error while attempting to invoke the fsync() system call on Unix systems, or FlushFileBuffers() on Windows. This error occurs in the VFS (Virtual File System) layer when trying to flush previously written content from OS and disk-control buffers into persistent storage. The fsync() operation is critical for database durability and ACID guarantees. When SQLite commits a transaction, it needs to ensure that all changes have been physically written to disk before reporting success. A failure at this stage means that data you believed was safely stored may still be in volatile memory and at risk of loss during a power failure or crash. This error is distinct from SQLITE_FULL (database or disk is full) and indicates actual I/O failures rather than space constraints. Common underlying causes include filesystem corruption, failing storage hardware, incompatible network filesystems, or kernel-level I/O errors that prevent proper synchronization.

Typical symptoms

  • Transaction commits fail with "disk I/O error" messages
  • SQLite operations succeed initially but fail during commit
  • Application crashes or hangs when writing to the database
  • Error code 1034 or SQLITE_IOERR_FSYNC appears in logs
  • Database writes work without synchronous mode but fail with FULL
  • Issues occur specifically on network-mounted filesystems (SMB/CIFS/NFS)
  • Problems manifest after filesystem changes or remounting
  • fsync-related errors in system logs or kernel messages

Common causes

  1. Failing or degraded storage hardware (HDD, SSD, SD card, USB drive)
  2. Filesystem corruption requiring fsck or repair utilities
  3. Network filesystem limitations (SMB/CIFS without proper POSIX locking support)
  4. F2FS or other modern filesystems with non-standard fsync behavior
  5. Kernel bugs or driver issues preventing proper disk synchronization
  6. Invalid file descriptor caused by another module closing the file
  7. Read-only filesystem mounted without proper write permissions
  8. Storage device disconnected or unmounted during operation
  9. Virtual machine or container storage with incomplete sync support
  10. Disk controller or RAID array errors blocking write operations

How to fix "SQLITE_IOERR_FSYNC: Error during fsync()"

1Enable SQLite logging to identify the affected file

Configure SQLite to log detailed error information using SQLITE_CONFIG_LOG. This will identify which specific file the fsync() call failed on.

c
#include <sqlite3.h>

void error_log_callback(void *pArg, int iErrCode, const char *zMsg) {
    fprintf(stderr, "SQLite Error [%d]: %s\n", iErrCode, zMsg);
}

// During initialization
sqlite3_config(SQLITE_CONFIG_LOG, error_log_callback, NULL);

In Python:

python
import sqlite3
import logging

# Enable SQLite trace
sqlite3.enable_callback_tracebacks(True)

# Log errors
def log_sqlite_error(errno, msg):
    logging.error(f"SQLite error {errno}: {msg}")

Check the logs for messages indicating which file descriptor or database file is failing.

2Check filesystem health and repair if needed

Run filesystem integrity checks to identify and repair corruption that may prevent fsync operations.

For ext4 filesystems:

bash
# Unmount the filesystem first
sudo umount /dev/sdX1

# Run filesystem check
sudo fsck -f /dev/sdX1

# Remount
sudo mount /dev/sdX1 /mnt/point

For other filesystems:

bash
# F2FS
fsck.f2fs /dev/sdX1

# XFS
xfs_repair /dev/sdX1

# Check system logs
dmesg | grep -i error
journalctl -xe | grep -i sqlite

Review the output for I/O errors or filesystem inconsistencies.

3Test storage hardware for failures

Use diagnostic tools to check if the storage device is failing.

Check SMART status:

bash
# Install smartmontools
sudo apt-get install smartmontools

# Check disk health
sudo smartctl -a /dev/sdX

# Look for reallocated sectors, pending sectors, or other warnings
sudo smartctl -H /dev/sdX

Run read/write tests:

bash
# Test disk performance (WARNING: destroys data on the device)
sudo dd if=/dev/zero of=/dev/sdX bs=1M count=1000

# Test filesystem write/sync
sync && echo 3 | sudo tee /proc/sys/vm/drop_caches
dd if=/dev/zero of=/mnt/testfile bs=1M count=100 oflag=dsync
rm /mnt/testfile

If SMART errors appear or writes fail, replace the storage device immediately.

4Verify filesystem mount options and permissions

Ensure the filesystem is mounted with proper sync support and write permissions.

Check current mount options:

bash
mount | grep /path/to/database

# Look for read-only or noatime flags that might interfere
cat /proc/mounts | grep /mnt/point

For network filesystems (SMB/CIFS), add proper mount options:

bash
# Mount SMB with better SQLite support
sudo mount -t cifs //server/share /mnt/point \
  -o username=user,uid=1000,gid=1000,file_mode=0660,dir_mode=0770,nobrl

# Or in /etc/fstab
//server/share /mnt/point cifs credentials=/etc/samba/credentials,nobrl,uid=1000 0 0

The nobrl (no byte range locking) option can help with SQLite on SMB shares, though local storage is always preferred.

5Move database to local filesystem if on network storage

Network filesystems often lack proper POSIX locking and fsync support. Moving the database to local storage resolves many fsync issues.

bash
# Copy database to local storage
cp /mnt/network/database.db /var/lib/app/database.db

# Update application configuration
# In your app config or environment
DATABASE_PATH=/var/lib/app/database.db

In your application:

python
import sqlite3
import os

# Prefer local storage
if os.path.exists('/mnt/network/app'):
    # Use local database path
    db_path = '/var/lib/app/database.db'
else:
    db_path = '/mnt/network/database.db'

conn = sqlite3.connect(db_path)

SQLite works best on local ext4, XFS, or Btrfs filesystems. Network storage should only be used for backups or read-only access.

6Adjust synchronous pragma as a temporary workaround

If you cannot resolve the underlying I/O issue immediately, you can temporarily reduce sync requirements, but this increases data loss risk.

sql
-- Check current synchronous setting
PRAGMA synchronous;

-- Reduce to NORMAL (default is FULL)
PRAGMA synchronous = NORMAL;

-- Or PRAGMA synchronous = 1;

In application code:

python
import sqlite3

conn = sqlite3.connect('database.db')
# FULL (2) - Maximum safety, fsync on every commit
# NORMAL (1) - Sync at critical moments (default for WAL mode)
# OFF (0) - No sync, fastest but dangerous
conn.execute('PRAGMA synchronous = NORMAL')
javascript
const sqlite3 = require('better-sqlite3');
const db = sqlite3('database.db');

// Set to NORMAL mode
db.pragma('synchronous = NORMAL');

WARNING: Setting synchronous to OFF or NORMAL increases the risk of database corruption during power failures or crashes. Only use this as a temporary workaround while diagnosing the root cause. For production systems, always use FULL (the default).

7Check for file descriptor conflicts

Ensure no other code or process is closing the database file descriptor while SQLite is using it.

bash
# Find processes with the database file open
lsof /path/to/database.db

# Check for multiple processes
ps aux | grep your-app

In your application, verify file descriptor management:

python
import sqlite3

# Use context manager to ensure proper cleanup
with sqlite3.connect('database.db') as conn:
    # Your database operations
    conn.execute('INSERT INTO users VALUES (?)', (name,))
    # Connection closed automatically on exit
javascript
// Ensure single connection instance
const sqlite3 = require('better-sqlite3');

class Database {
    constructor(path) {
        if (!Database.instance) {
            Database.instance = sqlite3(path);
        }
        return Database.instance;
    }
}

const db = new Database('database.db');

Avoid opening multiple connections to the same database file simultaneously, especially in multi-threaded applications.

Advanced notes

### F2FS-Specific Issues

Some F2FS configurations can trigger SQLITE_IOERR_FSYNC errors, particularly with fsync_mode=posix. If using F2FS, try different fsync modes:

bash
# Check current F2FS mount options
mount | grep f2fs

# Remount with different fsync mode
sudo mount -o remount,fsync_mode=nobarrier /dev/sdX1

### Kernel fsync Error Recovery

When fsync() fails at the kernel level, Linux marks dirty pages as clean and reports the error once. This means subsequent fsync() calls may succeed even though data was never written. This is a fundamental limitation described in "fsyncgate" research—once fsync fails, recovery is extremely difficult.

Applications cannot reliably recover from fsync failures. The only safe response is to fail the transaction and alert operators to investigate the underlying storage issue.

### WAL Mode and Network Filesystems

SQLite's WAL (Write-Ahead Logging) mode has stricter requirements for filesystem locking and synchronization. On SMB/CIFS shares without proper support:

sql
-- Check current journal mode
PRAGMA journal_mode;

-- Switch to DELETE mode if on network storage
PRAGMA journal_mode = DELETE;

However, this reduces concurrency benefits. The proper solution is always to use local storage for SQLite databases.

### Virtual Machine Storage Concerns

VMs and containers may have incomplete fsync support depending on the host configuration. Ensure:
- Host filesystem supports fsync properly
- VM disk images are on local storage, not network mounts
- Disk caching is configured for safety (writethrough or writeback with battery-backed cache)
- virtio-scsi or virtio-blk drivers are used with cache=none or cache=directsync

### Monitoring and Alerting

Implement monitoring for SQLITE_IOERR_FSYNC errors in production:

python
import sqlite3
import logging

class SafeDatabase:
    def __init__(self, path):
        self.conn = sqlite3.connect(path)
        self.ioerr_count = 0

    def execute(self, query, params=()):
        try:
            return self.conn.execute(query, params)
        except sqlite3.OperationalError as e:
            if 'disk I/O error' in str(e):
                self.ioerr_count += 1
                logging.critical(f"SQLITE_IOERR_FSYNC detected! Count: {self.ioerr_count}")
                # Alert operations team
                send_alert("Database fsync failure")
            raise

Set up alerts when these errors occur, as they indicate serious infrastructure problems requiring immediate attention.

Frequently asked questions

What does "SQLITE_IOERR_FSYNC" mean?
SQLITE_IOERR_FSYNC is an extended error code (1034) that indicates SQLite encountered an I/O error while attempting to invoke the fsync() system call on Unix systems, or FlushFileBuffers() on Windows. This error occurs in the VFS (Virtual File System) layer when trying to flush previously written content from OS and disk-control buffers into persistent storage. The fsync() operation is critical for database durability and ACID guarantees.
How do I fix "SQLITE_IOERR_FSYNC"?
SQLite failed to flush buffered data to persistent storage via the fsync() system call. This extended I/O error (code 1034) occurs when the operating system cannot sync written data to disk.
What causes "SQLITE_IOERR_FSYNC"?
Failing or degraded storage hardware (HDD, SSD, SD card, USB drive) Filesystem corruption requiring fsck or repair utilities Network filesystem limitations (SMB/CIFS without proper POSIX locking support)
Is the "SQLITE_IOERR_FSYNC" error serious?
Yes. This is a critical-severity error that usually blocks work until it is fixed, but the steps above resolve it.

Official resources & further reading