ZetCode

Python sqlite3.DatabaseError Exception

Last modified April 15, 2025

This comprehensive guide explores Python's sqlite3.DatabaseError exception, which handles database-related errors in SQLite operations.

Basic Definitions

The sqlite3.DatabaseError is a base class for database-related exceptions in Python's sqlite3 module. It inherits from sqlite3.Error.

This exception is raised for errors that are related to the database itself, not programming mistakes. It covers issues like corrupt databases, disk I/O errors, and other database-specific problems.

Handling DatabaseError

This example shows basic error handling for DatabaseError when working with SQLite databases.

basic_error_handling.py
import sqlite3

try:
    with sqlite3.connect("example.db") as conn:
        cursor = conn.cursor()
        cursor.execute("SELECT * FROM non_existent_table")
except sqlite3.DatabaseError as e:
    print(f"Database error occurred: {e}")
except Exception as e:
    print(f"Other error occurred: {e}")

This code attempts to query a non-existent table, which raises a DatabaseError. The with statement ensures resources are properly closed.

The example demonstrates proper exception handling hierarchy, catching specific database errors first before more general exceptions.

Corrupt Database File

This example shows how DatabaseError is raised when working with a corrupt SQLite database file.

corrupt_database.py
import sqlite3

try:
    with sqlite3.connect("corrupt.db") as conn:
        cursor = conn.cursor()
        cursor.execute("SELECT * FROM test")
except sqlite3.DatabaseError as e:
    print(f"Database corruption detected: {e}")
    # Here you might attempt recovery or notify the user

When SQLite detects database corruption, it raises DatabaseError. The exact message depends on the corruption type and location.

In production code, you might implement recovery procedures or user notifications when detecting corruption.

Disk I/O Errors

This example demonstrates handling disk I/O errors that manifest as DatabaseError exceptions.

disk_io_error.py
import sqlite3

try:
    # Attempt to create database in read-only location
    with sqlite3.connect("/readonly/location/test.db") as conn:
        cursor = conn.cursor()
        cursor.execute("CREATE TABLE test (id INTEGER)")
except sqlite3.DatabaseError as e:
    print(f"Disk I/O error occurred: {e}")
    # Handle the error (e.g., fallback location)

Disk I/O errors occur when SQLite can't read from or write to the database file. This might happen due to permissions or filesystem issues.

The example shows how to catch these errors and potentially implement fallback behavior in your application.

Transaction Errors

This example shows how transaction-related issues can raise DatabaseError exceptions.

transaction_error.py
import sqlite3

try:
    with sqlite3.connect("transactions.db") as conn:
        cursor = conn.cursor()
        cursor.execute("BEGIN IMMEDIATE")
        cursor.execute("INSERT INTO accounts VALUES (1, 100)")
        # Simulate error during transaction
        raise RuntimeError("Unexpected error")
        conn.commit()
except sqlite3.DatabaseError as e:
    print(f"Transaction error: {e}")
except Exception as e:
    print(f"Other error: {e}")
    # Connection's __exit__ will rollback automatically

Transaction errors can occur when there are issues committing or rolling back changes. The with statement ensures proper rollback on exceptions.

This pattern is crucial for maintaining database consistency when errors occur during transactions.

Database Schema Errors

This example demonstrates handling schema-related DatabaseError exceptions.

schema_error.py
import sqlite3

try:
    with sqlite3.connect("schema.db") as conn:
        cursor = conn.cursor()
        # Attempt invalid schema change
        cursor.execute("ALTER TABLE users ADD COLUMN email UNIQUE")
except sqlite3.DatabaseError as e:
    print(f"Schema modification failed: {e}")
    # Handle the error (e.g., alternative schema change)

Schema errors occur when attempting invalid database schema modifications. SQLite has specific rules for schema changes that must be followed.

The example shows how to catch these errors and potentially implement alternative schema modification strategies.

Database Locking Errors

This example shows how to handle database locking issues that raise DatabaseError.

locking_error.py
import sqlite3
import time

def attempt_operation():
    try:
        with sqlite3.connect("busy.db", timeout=1.0) as conn:
            cursor = conn.cursor()
            cursor.execute("UPDATE counters SET value = value + 1")
            conn.commit()
            return True
    except sqlite3.DatabaseError as e:
        print(f"Database locked, retrying... ({e})")
        return False

# Retry logic for locked database
for attempt in range(3):
    if attempt_operation():
        break
    time.sleep(1)
else:
    print("Failed to acquire database lock after 3 attempts")

Locking errors occur when multiple processes attempt to modify the database simultaneously. The example implements a retry mechanism.

The timeout parameter specifies how long to wait for the lock before raising an exception.

Custom Error Handling

This example demonstrates advanced error handling with custom behavior for different DatabaseError scenarios.

custom_error_handling.py
import sqlite3

def handle_database_error(error):
    error_msg = str(error).lower()
    if "corrupt" in error_msg:
        print("Database corruption detected - initiating recovery")
        # Start recovery process
    elif "locked" in error_msg:
        print("Database locked - implement retry logic")
        # Implement retry logic
    elif "disk i/o" in error_msg:
        print("Disk I/O error - check storage")
        # Check storage availability
    else:
        print(f"Unhandled database error: {error}")

try:
    with sqlite3.connect("app.db") as conn:
        cursor = conn.cursor()
        cursor.execute("SELECT * FROM critical_data")
except sqlite3.DatabaseError as e:
    handle_database_error(e)
except Exception as e:
    print(f"Non-database error occurred: {e}")

This example shows how to implement sophisticated error handling that responds differently to various database error conditions.

The custom handler examines the error message to determine appropriate recovery actions for different scenarios.

Best Practices

Source References

Author

My name is Jan Bodnar, and I am a passionate programmer with extensive programming experience. I have been writing programming articles since 2007. To date, I have authored over 1,400 articles and 8 e-books. I possess more than ten years of experience in teaching programming.

List all Python tutorials.