Skip to content

Bug: native addon load fails when postinstall is skipped (pnpm dlx / --ignore-scripts) despite per-platform binary being present #20

Description

@tupe12334

Environment

  • OS: macOS arm64 (darwin-arm64)
  • Node: v25.9.0
  • @ladybugdb/core: 0.16.1
  • Repro command: pnpm dlx gitnexus@latest serve

Symptom

At runtime the native addon fails to load:

Error: dlopen(.../node_modules/@ladybugdb/core/lbugjs.node, 0x0001): tried: '.../@ladybugdb/core/lbugjs.node' (no such file) ...
    at Object.<anonymous> (.../@ladybugdb/core/lbug_native.js:22:11)  // process.dlopen(lbugNativeModule, modulePath)
  code: 'ERR_DLOPEN_FAILED'

Root cause

The prebuilt binary ships in a per-platform sub-package (@ladybugdb/core-darwin-arm64, etc.) and the file lbugjs.node is present there. The package's install.js (postinstall) is what resolves that sub-package via

require.resolve(`${MAIN_PKG_NAME}-${platform}-${arch}/package.json`, { paths: [__dirname] })

and copies the binary into the main package where the runtime loader lbug_native.js expects it.

However, pnpm dlx / pnpx / npm install --ignore-scripts / sandboxed installs do not run lifecycle scripts, so install.js never runs, the binary is never placed, and the runtime loader fails because it only looks at the in-package path (@ladybugdb/core/lbugjs.node).

Verified directly: the file exists at @ladybugdb/core-darwin-arm64/.../lbugjs.node but not at @ladybugdb/core/lbugjs.node.

Distinct from existing issues

  • #436 (darwin-x64 sub-package unpublished) — there the sub-package/binary was missing/unpublished. Here the binary exists and is published.
  • #303 (missing prebuilt) — same: prebuilt missing. Here the prebuilt is present in the sub-package.

The problem here is purely that the runtime loader has no fallback when postinstall didn't run.

Proposed fix

Make the runtime native loader (lbug_native.js) resilient: when the in-package lbugjs.node is missing, fall back to resolving the binary directly from the per-platform sub-package at runtime — reusing the exact require.resolve(${pkgName}-${platform}-${arch}/...) logic that install.js already contains. This fixes pnpm dlx, --ignore-scripts, and sandboxed environments without requiring the postinstall copy step.

🤖 Generated with Claude Code

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions