Fixing NativeWind v4 Metro Configuration Error in Expo

15 November 2025

The Problem

When attempting to run the iOS development server with bun run ios, the build failed with this error:

Error: Found config at /Users/waf/Documents/Projects/charades/metro.config.js
that could not be loaded with Node.js.

This generic error message provided little insight into the actual problem.

Root Cause

The cryptic "could not be loaded" error was actually Metro's way of reporting that the NativeWind Metro plugin encountered an error during configuration loading. When Metro loads metro.config.js, it executes the withNativeWind() function, which validates the Tailwind configuration. If that validation fails, Metro reports it as a config loading error rather than surfacing the underlying issue.

The actual problem was in the tailwind.config.js file, which was missing two critical components required by NativeWind v4:

  1. Missing NativeWind preset - The configuration didn't include presets: [require("nativewind/preset")]
  2. Empty content array - Tailwind had no paths to scan for class usage

Without the preset, the withNativeWind() function throws an error during Metro config initialization, resulting in the misleading "could not be loaded" message.

The Solution

1. Updated tailwind.config.js

Before:

module.exports = {
  content: [],
  theme: {
    extend: {},
  },
  plugins: [],
}

After:

module.exports = {
  content: [
    "./app/**/*.{js,jsx,ts,tsx}",
    "./components/**/*.{js,jsx,ts,tsx}",
    "./hooks/**/*.{js,jsx,ts,tsx}",
  ],
  presets: [require("nativewind/preset")],
  theme: {
    extend: {},
  },
  plugins: [],
}

2. Metro Configuration (Confirmed Correct)

The metro.config.js was already properly configured:

const { getDefaultConfig } = require("expo/metro-config");
const { withNativeWind } = require("nativewind/metro");

const config = getDefaultConfig(__dirname);

module.exports = withNativeWind(config, { input: "./global.tailwind.css" });

Additional Troubleshooting: Node.js Version Compatibility

If you're still experiencing issues after fixing the Tailwind configuration, check your Node.js version:

  • Node.js v19.x compatibility issues - Some users reported that Node.js v19.3.0 caused errors with Metro's os.availableParallelism() function
  • Recommended: Use Node.js v22 or LTS - Upgrading to Node.js v22 (or the current LTS version) resolves these compatibility issues
  • Avoid using Bun for Expo - While Bun works for many tasks, Expo's metro bundler expects Node.js-specific APIs. Use npx expo start --ios instead of bun run ios

To check your Node version: node --version To switch versions (if using nvm): nvm use 22

Key Takeaways

  • Metro config errors can be deceptive - When Metro reports it "could not load" a config file, the actual issue might be within a plugin or wrapper function that's executed during config initialization, not the config file itself
  • NativeWind v4 requires the preset - Unlike earlier versions, NativeWind v4 uses a Tailwind preset that must be explicitly added to tailwind.config.js. This is a breaking change from v2/v3
  • Content paths matter - Even though Metro handles the bundling, Tailwind still needs to know which files to scan for utility classes
  • Debug by elimination - When facing vague errors, verify each layer: first the config syntax, then the plugin requirements, then the dependencies

References

```