How to fix SQLITE_LOCKED_SHAREDCACHE: Conflict within shared cache in SQLite

SQLiteINTERMEDIATEMEDIUMUpdated Dec 29, 2025ยท 142 views

SQLITE_LOCKED_SHAREDCACHE occurs when multiple connections to the same database in shared-cache mode attempt conflicting operations simultaneously. This error indicates a table-level lock conflict and typically appears in multi-threaded applications. The recommended solution is to disable shared-cache mode or migrate to WAL mode, which handles concurrent access more efficiently.

Quick fix

Fixes SQLITE_LOCKED_SHAREDCACHE

// In-memory database with shared cache
DataSource=file::memory:?cache=shared

// Or using URI format
DataSource=:memory:?cache=shared

// Or the SQLITE_OPEN_SHAREDCACHE flag in your sqlite3_open_v2() call
  1. Verify shared-cache mode is enabled
  2. Remove shared-cache mode (recommended)
  3. Enable WAL mode (best for concurrency)
  4. If keeping shared-cache, implement retry logic
sqlite โ€” error
// In-memory database with shared cache
DataSource=file::memory:?cache=shared
// Or using URI format
DataSource=:memory:?cache=shared
// Or the SQLITE_OPEN_SHAREDCACHE flag in your sqlite3_open_v2() call
SQLITE_LOCKED_SHAREDCACHE: Conflict within shared cache

What this error means

The SQLITE_LOCKED_SHAREDCACHE error is a result code that indicates a write operation could not continue because of a locking conflict within a shared database cache. This occurs when shared-cache mode is enabled and multiple connections to the same database attempt to access the same table concurrently. In shared-cache mode, SQLite uses table-level locking instead of database-level locking. When one connection modifies data in a table, SQLite locks that table at a fine-grained level. If another connection tries to access the same locked table simultaneously, SQLite returns the SQLITE_LOCKED_SHAREDCACHE error rather than blocking and waiting. This is fundamentally different from normal SQLite locking behavior, where separate connections would lock the entire database file and typically receive SQLITE_BUSY instead of SQLITE_LOCKED.

Typical symptoms

  • Database operations fail intermittently with "SQLITE_LOCKED_SHAREDCACHE" error code
  • Errors occur specifically when multiple threads or connections access the database simultaneously
  • The application works fine with single-threaded access but fails under concurrent load
  • Setting a busy timeout or using PRAGMA busy_timeout has no effect on SQLITE_LOCKED errors
  • Errors are more frequent when one connection is writing while others are reading or writing to the same table

Common causes

  1. Shared-cache mode is explicitly enabled on one or more database connections
  2. Multiple connections share the same in-memory database with cache=shared parameter
  3. One connection holds a write lock or schema modification lock while another attempts to access the same table
  4. Schema modifications (ALTER TABLE, CREATE INDEX) are happening while other connections are reading or writing
  5. Concurrent read and write operations overlap on the same table without proper transaction isolation controls

How to fix "SQLITE_LOCKED_SHAREDCACHE: Conflict within shared cache"

1Verify shared-cache mode is enabled

Check if shared-cache mode is being used in your connection string or SQLite configuration. Look for:

bash
// In-memory database with shared cache
DataSource=file::memory:?cache=shared

// Or using URI format
DataSource=:memory:?cache=shared

// Or the SQLITE_OPEN_SHAREDCACHE flag in your sqlite3_open_v2() call

If you're using Microsoft.Data.Sqlite or another SQLite client, check the connection string for Cache=Shared.

2Remove shared-cache mode (recommended)

The simplest solution is to disable shared-cache mode. Change your connection string:

csharp
// Before (with shared cache - causes SQLITE_LOCKED_SHAREDCACHE)
var connectionString = "DataSource=file::memory:?cache=shared";

// After (private cache - default)
var connectionString = "DataSource=:memory:?cache=private";
// Or simply
var connectionString = "DataSource=:memory:";

// Or remove cache parameter entirely
var connectionString = "Data Source=mydata.db";

The default behavior is private-cache mode, which uses database-level locking and is more suitable for most applications.

3Enable WAL mode (best for concurrency)

If you need better concurrent access, migrate to Write-Ahead Logging (WAL) mode. WAL mode eliminates the need for shared-cache and provides significantly better concurrency:

csharp
// When creating your connection
var connectionString = "Data Source=mydata.db";
using (var connection = new SqliteConnection(connectionString))
{
    connection.Open();
    
    // Enable WAL mode
    using (var command = connection.CreateCommand())
    {
        command.CommandText = "PRAGMA journal_mode = WAL";
        command.ExecuteNonQuery();
    }
}

WAL mode (introduced in SQLite 3.7.0 around 2010) is the recommended solution for concurrent access. It allows readers and writers to coexist without blocking each other.

4If keeping shared-cache, implement retry logic

If you must use shared-cache mode (rare), implement exponential backoff retry logic since busy timeouts don't work with SQLITE_LOCKED:

csharp
const int maxRetries = 5;
int retryCount = 0;

while (retryCount < maxRetries)
{
    try
    {
        // Execute your database operation
        connection.Execute(sql);
        break; // Success
    }
    catch (SqliteException ex) when (ex.SqliteErrorCode == 6) // SQLITE_LOCKED
    {
        retryCount++;
        if (retryCount >= maxRetries) throw;
        
        // Exponential backoff
        int delayMs = (int)Math.Pow(2, retryCount) * 10;
        await Task.Delay(delayMs);
    }
}

Note: This is not ideal and should only be used as a temporary workaround.

5Verify the fix

After making changes:

1. Remove or comment out any code that explicitly enables shared-cache mode
2. Test concurrent database access from multiple threads
3. Monitor for SQLITE_LOCKED_SHAREDCACHE errors in logs
4. If using WAL mode, verify the -wal and -shm files are being created alongside your database file

csharp
// Test concurrent access
var tasks = Enumerable.Range(0, 10)
    .Select(i => Task.Run(() => ExecuteDatabaseOperation(i)))
    .ToArray();

await Task.WhenAll(tasks);
// Should complete without SQLITE_LOCKED_SHAREDCACHE errors

Advanced notes

Shared-cache mode is deprecated and discouraged by SQLite developers. It was originally designed for embedded systems (like Symbian phones) where database file locking was problematic. Modern applications should use WAL mode instead.

Key differences between shared-cache and normal locking:

- Normal mode: Multiple connections lock the entire database file; conflicts use SQLITE_BUSY with timeout support
- Shared-cache mode: Multiple connections lock individual tables; conflicts use SQLITE_LOCKED with no timeout support
- WAL mode: Uses a write-ahead log for concurrent access; supports multiple readers with one writer without file-level locking

Shared-cache mode also does not work well with WAL mode. If you're mixing these, remove the shared-cache mode.

For Node.js SQLite drivers like sqlite3 or better-sqlite3, check the documentation for equivalent configuration options. The principle remains the same: disable shared-cache mode or migrate to WAL.

Frequently asked questions

What does "SQLITE_LOCKED_SHAREDCACHE" mean?
The SQLITE_LOCKED_SHAREDCACHE error is a result code that indicates a write operation could not continue because of a locking conflict within a shared database cache. This occurs when shared-cache mode is enabled and multiple connections to the same database attempt to access the same table concurrently. In shared-cache mode, SQLite uses table-level locking instead of database-level locking.
How do I fix "SQLITE_LOCKED_SHAREDCACHE"?
SQLITE_LOCKED_SHAREDCACHE occurs when multiple connections to the same database in shared-cache mode attempt conflicting operations simultaneously. This error indicates a table-level lock conflict and typically appears in multi-threaded applications. The recommended solution is to disable shared-cache mode or migrate to WAL mode, which handles concurrent access more efficiently.
What causes "SQLITE_LOCKED_SHAREDCACHE"?
Shared-cache mode is explicitly enabled on one or more database connections Multiple connections share the same in-memory database with cache=shared parameter One connection holds a write lock or schema modification lock while another attempts to access the same table
Is the "SQLITE_LOCKED_SHAREDCACHE" error serious?
It is a medium-severity error โ€” more of a blocker than a risk. The steps above resolve it.

Official resources & further reading