Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

"Failed to load native binding" with @node-rs/bcrypt + Expo Router API Routes (Metro bundler) #911

Open
karlhorky opened this issue Oct 25, 2024 · 0 comments

Comments

@karlhorky
Copy link

karlhorky commented Oct 25, 2024

Companion issue (expo/expo): expo/expo#32350

Hi, first of all, thanks for these Rust libraries! Nice performance, and good options when the main bcrypt, etc packages don't work in a particular environment.

We are trying to use @node-rs/bcrypt in Expo Router API Routes (using Metro bundler), and we're getting some output that the native binding cannot be loaded (because it's "undefined", see further below):

Android Bundled 852ms node_modules/expo-router/entry.js (1049 modules)
λ Bundled 443ms app/hash+api.ts (4 modules)

Metro error: Failed to load native binding

  357 |     //  - The user may need to bundle the correct files
  358 |     //  - The user may need to re-install node_modules to get new packages
> 359 |     throw new Error('Failed to load native binding', { cause: loadErrors })
      |           ^
  360 |   }
  361 |   throw new Error(`Failed to load native binding`)
  362 | }

Call Stack
  factory (node_modules/@node-rs/bcrypt/binding.js:359:11)
  loadModuleImplementation (node_modules/metro-runtime/src/polyfills/require.js:277:5)
  guardedLoadModule (node_modules/metro-runtime/src/polyfills/require.js:184:12)
  require (node_modules/metro-runtime/src/polyfills/require.js:92:7)
  factory (node_modules/@node-rs/bcrypt/index.js:1:84)
  loadModuleImplementation (node_modules/metro-runtime/src/polyfills/require.js:277:5)
  guardedLoadModule (node_modules/metro-runtime/src/polyfills/require.js:184:12)
  require (node_modules/metro-runtime/src/polyfills/require.js:92:7)
  factory (app/hash+api.ts:1)
  loadModuleImplementation (node_modules/metro-runtime/src/polyfills/require.js:277:5)
 ERROR  [SyntaxError: JSON Parse error: Unexpected character: <]

Screenshot 2024-10-25 at 15 43 50

I think Metro is not logging out the error cause, so adapting the node_modules/@node-rs/bcrypt/binding.js to log out loadErrors shows that it is using "undefined" as the module specifier:

if (!nativeBinding) {
  if (loadErrors.length > 0) {
    // TODO Link to documentation with potential fixes
    //  - The package owner could build/publish bindings for this arch
    //  - The user may need to bundle the correct files
    //  - The user may need to re-install node_modules to get new packages
+   console.log(loadErrors[0])
+   console.log(loadErrors[1])
+   console.log(loadErrors[2])
+   console.log(loadErrors[3])
    throw new Error('Failed to load native binding', { cause: loadErrors })
  }
  throw new Error(`Failed to load native binding`)
}

This is repeated 4 times:

λ  LOG  Error: Requiring unknown module "undefined". If you are sure the module exists, try restarting Metro. You may also want to run `yarn` or `npm install`.
    at unknownModuleError (/Users/k/p/repro-expo-router-api-routes-node-rs-bcrypt/node_modules/metro-runtime/src/polyfills/require.js:322:10)
    at loadModuleImplementation (/Users/k/p/repro-expo-router-api-routes-node-rs-bcrypt/node_modules/metro-runtime/src/polyfills/require.js:244:11)
    at guardedLoadModule (/Users/k/p/repro-expo-router-api-routes-node-rs-bcrypt/node_modules/metro-runtime/src/polyfills/require.js:184:12)
    at require (/Users/k/p/repro-expo-router-api-routes-node-rs-bcrypt/node_modules/metro-runtime/src/polyfills/require.js:92:7)
    at requireNative (/Users/k/p/repro-expo-router-api-routes-node-rs-bcrypt/node_modules/@node-rs/bcrypt/binding.js:130:16)
    at factory (/Users/k/p/repro-expo-router-api-routes-node-rs-bcrypt/node_modules/@node-rs/bcrypt/binding.js:332:17)
    at loadModuleImplementation (/Users/k/p/repro-expo-router-api-routes-node-rs-bcrypt/node_modules/metro-runtime/src/polyfills/require.js:277:5)
    at guardedLoadModule (/Users/k/p/repro-expo-router-api-routes-node-rs-bcrypt/node_modules/metro-runtime/src/polyfills/require.js:184:12)
    at require (/Users/k/p/repro-expo-router-api-routes-node-rs-bcrypt/node_modules/metro-runtime/src/polyfills/require.js:92:7)
    at /Users/k/p/repro-expo-router-api-routes-node-rs-bcrypt/node_modules/@node-rs/bcrypt/index.js:1:84

Reproduction

Creation steps:

  1. mkdir repro-expo-router-api-routes-node-rs-bcrypt && cd repro-expo-router-api-routes-node-rs-bcrypt
  2. npx create-expo-app@latest .
  3. rm -r ./node_modules && npm install (for EMFILE error)
  4. Remove extra files
  5. Configure app.json with expo.web.output = "server" and expo.plugins[0][1] = { "origin": "http://localhost:8081" }
  6. Create a file app/hash+api.ts, with an Expo Router API Route, using hashSync from @node-rs/bcrypt
  7. Inside app/(tabs)/index.tsx, add a fetch() of the API Route inside useFocusEffect
  8. 💥 npm start and observe the error after API Route bundling
@karlhorky karlhorky changed the title Usage of @node-rs/bcrypt in Expo Router API Routes (Metro bundler) "Failed to load native binding" with @node-rs/bcrypt + Expo Router API Routes (Metro bundler) Oct 25, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant