node-odbc icon indicating copy to clipboard operation
node-odbc copied to clipboard

[BUG] MacOS - Library not loaded

Open bmenant opened this issue 4 months ago • 2 comments

Describe your system

  • odbc Package Version: 2.4.9
  • ODBC Driver: N/A
  • Database Name: N/A
  • Database Version: N/A
  • Database OS: N/A
  • Node.js Version: 22.18.0
  • Node.js OS: MacOS arm64

UnixODBC v2.3.12 has been compiled and installed directly from (there is no homebrew on this machine).

Describe the bug

On MacOS arm64, node-odbc expects UnixODBC to have been installed with homebrew... which is not always the case:

Error: dlopen(/Users/***/Sources/test-odbc/node_modules/odbc/lib/bindings/napi-v8/odbc.node, 0x0001): Library not loaded: /opt/homebrew/opt/unixodbc/lib/libodbc.2.dylib
  Referenced from: <23A3A8E6-3C18-3B8C-8B41-029DF327C740> /Users/***/Sources/test-odbc/node_modules/odbc/lib/bindings/napi-v8/odbc.node
  Reason: tried: '/opt/homebrew/opt/unixodbc/lib/libodbc.2.dylib' (no such file), '/System/Volumes/Preboot/Cryptexes/OS/opt/homebrew/opt/unixodbc/lib/libodbc.2.dylib' (no such file), '/opt/homebrew/opt/unixodbc/lib/libodbc.2.dylib' (no such file)
    at Object..node (node:internal/modules/cjs/loader:1846:18)
    at Module.load (node:internal/modules/cjs/loader:1423:32)
    at Function._load (node:internal/modules/cjs/loader:1246:12)
    at TracingChannel.traceSync (node:diagnostics_channel:322:14)
    at wrapModuleLoad (node:internal/modules/cjs/loader:235:24)
    at Module.require (node:internal/modules/cjs/loader:1445:12)
    at require (node:internal/modules/helpers:135:16)
    at Object.<anonymous> (/Users/***/Sources/test-odbc/node_modules/odbc/lib/odbc.js:6:20)
    at Module._compile (node:internal/modules/cjs/loader:1688:14)
    at Object..js (node:internal/modules/cjs/loader:1820:10) {
  code: 'ERR_DLOPEN_FAILED'
}

Expected behavior

node-odbc can load libraries from standard paths under /usr/local/*

To Reproduce Steps to reproduce the behavior:

  1. On a fresh MacOS instance, install x-code, compile and install UnixODBC (https://www.unixodbc.org/) and install Node.js from prebuilt MacOS arm64.
  2. Install a driver and configure UnixODBC.
  3. In a new directory, npm install odbc and copy index.mjs (see below)
  4. Run node index.mjs

Code

import odbc from 'odbc'; 

const sql = 'SELECT 1 AS TestCol1';
const connectionStr = 'DSN=XXX;Server=localhost;UID=XXX;Database=XXX';

odbc.connect(connectionStr)
	.then(conn => conn.query(sql))
	.then(result => console.log(result))
	.catch(reason => console.error(reason));

Additional context

A workaround is to create symbolic links to libs where node-odbc is looking at:

sudo mkdir -p /opt/homebrew/opt/unixodbc
sudo ln -s /usr/local/include /opt/homebrew/include
sudo ln -s /usr/local/lib /opt/homebrew/lib
sudo ln -s /usr/local/lib /opt/homebrew/opt/unixodbc/lib

bmenant avatar Sep 08 '25 13:09 bmenant

Another workaround would be to run install_name_tool on /Users/***/Sources/test-odbc/node_modules/odbc/lib/bindings/napi-v8/odbc.node to change the load path for libodbc.2.dylib or add an RPATH for /usr/local to it.

So what you'd like to see is libodbc.2.dylib is loaded via @rpath and /usr/local/lib is added as an RPATH entry to the library?

kadler avatar Sep 08 '25 14:09 kadler

So what you'd like to see is libodbc.2.dylib is loaded via @rpath and /usr/local/lib is added as an RPATH entry to the library?

I’m not familiar with MacOS library resolution, but this sounds good to me.

bmenant avatar Sep 08 '25 14:09 bmenant