Skip to content

Bug: customSqlitePath config is ignored on macOS - Apple SQLite always used #34

@mrcn

Description

@mrcn

Bug Description

The customSqlitePath configuration option in ~/.config/opencode/opencode-mem.jsonc is being ignored on macOS. Even when Homebrew SQLite is installed and configured, opencode-mem still attempts to use Apple'"'"'s system SQLite (which does not support dynamic extension loading).

Environment

  • OS: macOS (Darwin)
  • opencode-mem version: 2.8.4 and 2.8.7 (tested both)
  • Node.js/bun: Latest opencode-ai 1.2.6
  • Homebrew SQLite: Installed at /usr/local/opt/sqlite/lib/libsqlite3.dylib

Steps to Reproduce

  1. Install Homebrew SQLite:

    brew install sqlite
  2. Create config file at ~/.config/opencode/opencode-mem.jsonc:

    {
      "customSqlitePath": "/usr/local/opt/sqlite/lib/libsqlite3.dylib"
    }
  3. Verify the file exists:

    ls -la /usr/local/opt/sqlite/lib/libsqlite3.dylib
    # lrwxr-xr-x 1 user admin 23 Jul 30 2025 /usr/local/opt/sqlite/lib/libsqlite3.dylib -> libsqlite3.3.50.4.dylib
  4. Run opencode:

    opencode

Expected Behavior

opencode-mem should use the Homebrew SQLite library specified in customSqlitePath, which supports dynamic extension loading.

Actual Behavior

Error is thrown:

Error: Failed to load sqlite-vec extension: Error: This build of sqlite3 does not support dynamic extension loading

This usually means SQLite extension loading is disabled.
On macOS, you must use Homebrew SQLite instead of Apple'"'"'s SQLite.

Root Cause Analysis

Looking at src/services/sqlite/connection-manager.ts (lines ~61-65):

try {
  Database.setCustomSQLite(customPath);
} catch (error) {
  const errorStr = String(error);
  if (errorStr.includes("SQLite already loaded")) {
    // Empty catch - silently ignores the error!
  } else {
    throw new Error(...);
  }
}

The issue is that when you import { Database } from \"bun:sqlite\" at the top of the file, it immediately loads Apple'"'"'s SQLite. By the time configureSqlite() runs and calls setCustomSQLite(), it'"'"'s too late - SQLite is already loaded. The "SQLite already loaded" error is silently caught and ignored, causing the code to continue with Apple'"'"'s SQLite instead of the configured Homebrew SQLite.

Suggested Fix

The setCustomSQLite() call must happen before the Database is imported. Two possible approaches:

  1. Lazy import: Import bun:sqlite only after setCustomSQLite() has been called:

    // At top of file, don'"'"'t import Database yet
    let Database: typeof import("bun:sqlite").Database;
    
    configureSqlite() {
      if (this.sqliteConfigured) return;
      if (process.platform === "darwin" && customPath) {
        const { Database: BunDatabase } = await import("bun:sqlite");
        BunDatabase.setCustomSQLite(customPath);
        Database = BunDatabase;
      }
    }
  2. Separate initialization module: Create a separate module that configures SQLite before any database operations.

  3. Fail loudly: If customSqlitePath is configured but setCustomSQLite() throws "SQLite already loaded", throw an error instead of silently continuing:

    if (errorStr.includes("SQLite already loaded")) {
      throw new Error(
        `SQLite already loaded before custom path could be set. ` +
        `The customSqlitePath configuration requires SQLite to be configured before any database operations.`
      );
    }

Workarounds Attempted

  • ✅ Homebrew SQLite is installed and working
  • ✅ Config file created at correct path
  • ✅ Updated to opencode-mem 2.8.7 (latest)
  • ❌ Error persists because the bug is in the loading order

Additional Context

This affects all macOS users who try to use the customSqlitePath configuration option. The error message suggests this configuration as the solution, but the configuration is currently non-functional due to this bug.

Related issues:

  • Similar reports in sqlite-vec repo about macOS extension loading
  • The v2.7.6 changelog mentions "locking sqlite-vec to 0.1.7-alpha.2" but this appears to be a different fix

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions