Optional peer dependency expo-network crashes app when not installed #2645

Closed
opened 2026-03-13 10:10:39 -05:00 by GiteaMirror · 2 comments
Owner

Originally created by @marcospgp on GitHub (Jan 4, 2026).

Originally assigned to: @bytaesu on GitHub.

Is this suited for github?

  • Yes, this is suited for github

To Reproduce

@better-auth/expo declares expo-network as an optional peer dependency, but the app crashes at runtime if it's not installed.

Expected behavior

Optional dependencies should gracefully degrade when not present, not crash the app.

Actual behavior

ERROR  [Error: Cannot find native module 'ExpoNetwork']

Root cause

In dist/client.mjs, there's an unconditional dynamic import:

import("expo-network").then(({ addNetworkStateListener }) => {

Since it's a dynamic import, Metro still bundles the package if it exists in node_modules (which it does as a transitive dependency). When the import resolves, expo-network's JS tries to access the native module, which isn't linked because the user never ran expo install expo-network.

Suggested fix

Wrap the dynamic import in a try-catch:

import("expo-network")
  .then(({ addNetworkStateListener }) => {
    // use it
  })
  .catch(() => {
    // expo-network not available, gracefully degrade
  });

Or check if the native module exists before using it.

Environment

  • @better-auth/expo: 1.4.6
  • expo-network: 8.0.8 (optional peer)
  • Expo SDK: 54

Workaround

Explicitly install expo-network:

npx expo install expo-network

Current vs. Expected behavior

see above

What version of Better Auth are you using?

see above

System info

see above

Which area(s) are affected? (Select all that apply)

Package

Auth config (if applicable)

import { betterAuth } from "better-auth"
export const auth = betterAuth({
  emailAndPassword: {  
    enabled: true
  },
});

Additional context

No response

Originally created by @marcospgp on GitHub (Jan 4, 2026). Originally assigned to: @bytaesu on GitHub. ### Is this suited for github? - [x] Yes, this is suited for github ### To Reproduce `@better-auth/expo` declares `expo-network` as an optional peer dependency, but the app crashes at runtime if it's not installed. ### Expected behavior Optional dependencies should gracefully degrade when not present, not crash the app. ### Actual behavior ``` ERROR [Error: Cannot find native module 'ExpoNetwork'] ``` ### Root cause In `dist/client.mjs`, there's an unconditional dynamic import: ```js import("expo-network").then(({ addNetworkStateListener }) => { ``` Since it's a dynamic import, Metro still bundles the package if it exists in `node_modules` (which it does as a transitive dependency). When the import resolves, `expo-network`'s JS tries to access the native module, which isn't linked because the user never ran `expo install expo-network`. ### Suggested fix Wrap the dynamic import in a try-catch: ```js import("expo-network") .then(({ addNetworkStateListener }) => { // use it }) .catch(() => { // expo-network not available, gracefully degrade }); ``` Or check if the native module exists before using it. ### Environment - `@better-auth/expo`: 1.4.6 - `expo-network`: 8.0.8 (optional peer) - Expo SDK: 54 ### Workaround Explicitly install `expo-network`: ```bash npx expo install expo-network ``` ### Current vs. Expected behavior see above ### What version of Better Auth are you using? see above ### System info ```bash see above ``` ### Which area(s) are affected? (Select all that apply) Package ### Auth config (if applicable) ```typescript import { betterAuth } from "better-auth" export const auth = betterAuth({ emailAndPassword: { enabled: true }, }); ``` ### Additional context _No response_
GiteaMirror added the expo label 2026-03-13 10:10:39 -05:00
Author
Owner

@better-auth-agent[bot] commented on GitHub (Jan 4, 2026):

It looks like you are experiencing an issue with the @better-auth/expo package crashing due to the optional peer dependency expo-network. This issue arises because the app fails when expo-network is not installed, contrary to the expected behavior where optional dependencies should not cause crashes.

To resolve this, it's recommended to implement a try-catch around the dynamic import of expo-network in your code, as suggested in the steps provided. This should allow your application to handle the case where expo-network is not installed more gracefully:

try {
  const { addNetworkStateListener } = await import("expo-network");
  // use addNetworkStateListener as needed
} catch (error) {
  // Handle the case where expo-network is not available, enabling graceful degradation
}

This adjustment prevents the app from crashing when expo-network is not installed, which aligns with the expectations of handling optional dependencies gracefully [1], [2].

If you continue to experience issues or have more questions about Better Auth, feel free to ask! Have you already tried implementing the try-catch, or do you need assistance with another aspect of your setup?

If you need more help, tag @better-auth-agent in a comment so I can respond.

DiagramDiscordGitHub

Diagram Join Star

@better-auth-agent[bot] commented on GitHub (Jan 4, 2026): It looks like you are experiencing an issue with the `@better-auth/expo` package crashing due to the optional peer dependency `expo-network`. This issue arises because the app fails when `expo-network` is not installed, contrary to the expected behavior where optional dependencies should not cause crashes. To resolve this, it's recommended to implement a try-catch around the dynamic import of `expo-network` in your code, as suggested in the steps provided. This should allow your application to handle the case where `expo-network` is not installed more gracefully: ```javascript try { const { addNetworkStateListener } = await import("expo-network"); // use addNetworkStateListener as needed } catch (error) { // Handle the case where expo-network is not available, enabling graceful degradation } ``` This adjustment prevents the app from crashing when `expo-network` is not installed, which aligns with the expectations of handling optional dependencies gracefully [[1]](https://github.com/better-auth/better-auth/pull/6437), [[2]](https://github.com/better-auth/better-auth/issues/3668). If you continue to experience issues or have more questions about Better Auth, feel free to ask! Have you already tried implementing the try-catch, or do you need assistance with another aspect of your setup? _If you need more help, tag @better-auth-agent in a comment so I can respond._ <!-- bot:webhook reply v1 --> [Diagram](https://repodiagrams.s3.eu-north-1.amazonaws.com/skyvern_ultra_detailed_interactive.html) • [Discord](https://discord.gg/fG2XXEuQX3) • [GitHub](https://github.com/Skyvern-AI/Skyvern) [![Diagram](https://img.shields.io/badge/Diagram-2b3137?style=flat-square)](https://repodiagrams.s3.eu-north-1.amazonaws.com/skyvern_ultra_detailed_interactive.html) [![Join](https://img.shields.io/badge/join-5865F2?logo=discord&logoColor=white&style=flat-square)](https://discord.gg/fG2XXEuQX3) [![Star](https://img.shields.io/badge/star-181717?logo=github&logoColor=white&style=flat-square)](https://github.com/Skyvern-AI/Skyvern)
Author
Owner

@bytaesu commented on GitHub (Jan 8, 2026):

Thanks @marcospgp for letting me know

@bytaesu commented on GitHub (Jan 8, 2026): Thanks @marcospgp for letting me know
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#2645