Skip to content

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

@tupe12334

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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions