diegosouzapw/OmniRoute · error

[MCP Audit] better-sqlite3 binding unavailable — fell back…

Error message

[MCP Audit] better-sqlite3 binding unavailable — fell back to node:sqlite (${nativeMessage.split("\n")[0]})

What it means

Sentinel warning logged when better-sqlite3's native binding failed to load and the audit layer is falling back to Node's built-in node:sqlite DatabaseSync. It fires from openFallbackAuditDb whenever the primary native module throws (typically a NODE_MODULE_VERSION mismatch after a Node upgrade, or a missing prebuilt binary), meaning audit logging continues but through a different driver.

Solutions

  1. Run `npm rebuild better-sqlite3` in the omniroute install root to rebuild the native binding for the current Node version.
  2. Pin Node to a version with a matching better-sqlite3 prebuilt binary, or upgrade the better-sqlite3 dependency.
  3. If on Node >=22.5, accept the node:sqlite fallback — it is functional but verify audit performance is acceptable.
Defensive patterns

Strategy: fallback

When it happens

Trigger: Thrown at open-sse/mcp-server/audit.ts:259 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of diegosouzapw/OmniRoute@a179ffed5b (2026-08-25). Data as JSON: /api/errors/2cf6282d94eef97a. Report an issue: GitHub.

Appendix: source

Thrown at open-sse/mcp-server/audit.ts:259

  const { DatabaseSync } = (await import("node:sqlite")) as {
    DatabaseSync: new (p: string) => NodeSqliteDatabase;
  };
  return createNodeSqliteAuditAdapter(new DatabaseSync(dbPath));
}

async function openFallbackAuditDb(dbPath: string, nativeMessage: string): Promise<AuditDatabase | null> {
  if (!nodeSqliteFallbackAvailable()) {
    console.error(
      `[MCP Audit] better-sqlite3 native binding unavailable and Node ${process.version} ` +
        "has no built-in sqlite. Audit logging disabled. Fix: run " +
        "`npm rebuild better-sqlite3` in the omniroute install root."
    );
    return null;
  }

  try {
    const adapter = await openNodeSqliteAuditDb(dbPath);
    console.warn(
      `[MCP Audit] better-sqlite3 binding unavailable — fell back to node:sqlite ` +
        `(${nativeMessage.split("\n")[0]})`
    );
    return adapter;
  } catch (nodeErr) {
    const nodeMessage = nodeErr instanceof Error ? nodeErr.message : String(nodeErr);
    console.error("[MCP Audit] Failed to connect to database:", nodeMessage);
    return null;
  }
}

/**
 * Lazy-load the database connection.
 * Uses the same SQLite database as the main OmniRoute app.
 *
 * Driver priority:
 *   1. better-sqlite3 — fast native binding (when its compiled `.node`
 *      binary is present, see scripts/build/postinstall.mjs).

View on GitHub (pinned to a179ffed5b)