Why does a React Native 0.84 Android build fail with std::__ndk1 C++ linker errors using NDK 27? The answer is rooted in the intersection of new React Native native module architectures, C++20 requirements, quirks of the Android NDK toolchain, and platform-specific issues—especially on Windows. If you’re seeing mysterious linker errors mentioning missing std::__ndk1 symbols or failures in modules like react-native-reanimated, react-native-worklets, or react-native-screens, you’re not alone. Let’s unravel why this happens and how the community is wrestling with it.
Short answer: React Native 0.84 and related libraries increasingly rely on advanced C++20 features and updated build systems. While NDK 27 nominally supports C++20, on Windows—especially with the New Architecture enabled—NDK 27 can trigger “undefined symbol” linker errors related to std::__ndk1. These failures often stem from a combination of missing or mismatched standard library symbols, path length limitations, and subtle incompatibilities in Windows’ handling of the NDK/CMake toolchain. The errors are particularly acute for new-architecture builds, which involve more complex native code and stricter C++ requirements.
Let’s break down the situation in more detail.
The Rise of C++20 and Its Demands
React Native’s ecosystem—especially from version 0.81 onward—has increasingly adopted C++20 features for improved performance and modularity. For example, react-native-safe-area-context and other libraries now use constructs like std::format, which require a compliant C++20 standard library implementation.
According to aiuniverse.xyz, this shift means that NDK 26 “does not properly support this setup,” and projects will fail with errors such as “no member named 'format' in namespace 'std'.” The recommended fix is to “use NDK 27.1+,” as only these versions claim C++20 compatibility required by React Native 0.84 and above.
However, this is where the trouble starts—especially on Windows.
NDK 27, CMake, and the Windows Catch-22
Even after upgrading to NDK 27 and ensuring the correct ndkVersion is set in android/build.gradle (as described in detail on aiuniverse.xyz), many developers encounter a new wave of errors: linker failures for standard C++ functions. As described on github.com (expo/expo and software-mansion/react-native-reanimated), these typically take the form:
ld.lld: error: undefined symbol: std::runtime_error::~runtime_error() or ld.lld: error: undefined symbol: operator new(unsigned long)
These errors indicate that the linker cannot find basic implementations from the C++ standard library—std::__ndk1 refers to the namespace used by the Android NDK’s libc++ implementation. The problem is not that these functions don’t exist, but rather that the build system fails to correctly link them.
On Windows, this problem is especially pronounced. One user on github.com (software-mansion/react-native-reanimated) described it as “an unresolvable 'Catch-22' situation on a Windows development machine,” where enabling the New Architecture (needed for many modern React Native libraries) leads to persistent linker errors. Disabling the New Architecture, meanwhile, breaks compatibility with key libraries like Reanimated, which now require it.
The errors almost always occur during the buildCMakeDebug or configureCMakeDebug steps, and nearly always reference symbols from std::__ndk1 (such as operator new, std::runtime_error, or __cxa_... functions).
Why does this happen? The root causes, as synthesized from stackoverflow.com, aiuniverse.xyz, and several github.com issues, are:
1. **NDK Version Mismatch or Incomplete Installation**: Sometimes, the version of NDK referenced in build.gradle does not match the one actually installed. In other cases, as in a Stack Overflow post from October 2024, the NDK directory is missing the all-important source.properties file, so Gradle cannot determine the toolchain version and fails to resolve the correct standard library.
2. **Windows Path Length and File System Quirks**: On Windows, especially when using CMake and Ninja, deep directory nesting from the Gradle/.cxx and Prefab build systems can result in file paths exceeding 260 characters. According to github.com (software-mansion/react-native-screens), this triggers errors like “Filename longer than 260 characters,” which can cause Ninja or CMake to silently skip or fail to locate key .so or .a files—leading to missing symbols in the linker stage.
3. **Toolchain/Build System Incompatibilities**: The combination of NDK 27, CMake 3.22+, and React Native’s New Architecture is not always handled well by Windows’ file system and process environment. While Ubuntu-based CI systems (such as EAS Build) compile the same projects successfully, local Windows builds “fail with a C++ linker error related to the react-native-worklets package,” as described by a user on github.com (expo/expo). The root cause is often that the Windows build system can’t correctly find or link the standard library components needed for C++20 features.
4. **New Architecture Complexity**: With newArchEnabled=true, React Native’s Gradle and CMake scripts invoke more complex native module builds, which are sensitive to every aspect of the toolchain setup. If just one symbol or library is missing, the linker fails. On Windows, this is exacerbated by file system and path issues.
5. **NDK and CMake Caching Issues**: When switching between NDK versions or after a failed build, Gradle and CMake cache directories (.gradle, .cxx, app/.cxx) may contain stale or incompatible binaries. This is why guides such as aiuniverse.xyz emphasize always cleaning these directories after changing NDK versions.
Concrete Examples and Error Patterns
Let’s look at some very specific error signatures and their implications, drawn from across the sources:
- “error: no member named 'format' in namespace 'std' return std::format("{}%", dimension.value);” (aiuniverse.xyz) Indicates C++20 support is required, which NDK 26 lacks.
- “ld.lld: error: undefined symbol: std::runtime_error::~runtime_error()” (github.com, expo/expo) Suggests the linker cannot find libc++’s implementation of the C++ standard library, often due to build system misconfiguration or missing NDK components.
- “ld.lld: error: undefined symbol: operator new(unsigned long)” (github.com, software-mansion/react-native-reanimated) A symptom of standard library linking failure, usually in NDK/CMake builds with the New Architecture.
- “ninja: error: Stat(...): Filename longer than 260 characters” (github.com, software-mansion/react-native-screens) A uniquely Windows problem, causing native build steps to fail in ways that are not always obvious in the initial logs.
- “NDK at ... did not have a source.properties file” (stackoverflow.com) Means Gradle cannot verify or use the NDK, so the build cannot resolve toolchain dependencies.
Why This Is Worse on Windows
While the same React Native project may build perfectly on EAS Build (Ubuntu) with NDK 27.1, on Windows the native build system is far more brittle. As github.com (expo/expo) users report, “the same project builds fine on EAS Build (Ubuntu 24.04, NDK r27b),” but fails locally. This is because Windows’ handling of long file paths, environment variables, and the CMake/Ninja toolchain is less robust, and the NDK’s libc++ implementation is less forgiving of path or configuration errors.
Mitigations and Workarounds
So, what can you do? Here’s what the sources collectively recommend:
- **Ensure the Correct NDK Is Installed and Referenced**:
Always install NDK 27.1+ via Android Studio, and explicitly set ndkVersion in build.gradle to match the installed version. Double-check that the NDK directory includes source.properties.
- **Clean All Native Build Caches**:
Delete .gradle, .cxx, and app/.cxx when switching NDKs or after a failed build. This prevents stale binaries from breaking future builds (aiuniverse.xyz).
- **Use Short Directory Paths**:
Place your project in a root-level directory (like C:\proj) to minimize path length, reducing the risk of long-path errors (github.com, software-mansion/react-native-screens).
- **Enable Windows Long Path Support**:
Edit the appropriate registry key to enable long file paths on Windows 10/11, though this is not a complete solution due to limitations in Ninja and other tools.
- **Match Your Build Environment to CI/Cloud**:
If possible, use WSL2, Docker, or a Linux VM for native builds, as these environments are more reliable with NDK 27+ and complex C++20 code (github.com, expo/expo).
- **Check for Known Issues in Dependencies**:
Follow related issues on GitHub for react-native-reanimated, react-native-screens, and react-native-worklets, as maintainers may post workarounds or patches for Windows-specific problems.
A Complicated Landscape—But Some Hope
This issue is a classic example of how modern cross-platform development, with its blend of high-level JavaScript and low-level C++, can be derailed by subtle toolchain mismatches and OS-specific quirks. As one user summarized on github.com (software-mansion/react-native-reanimated), developers are caught in a “Catch-22” where enabling the features required by modern React Native libraries triggers build system failures that seem impossible to resolve on Windows.
To sum up, the std::__ndk1 C++ linker errors with NDK 27 in React Native 0.84 projects are not just about the NDK version—they’re about how the build system, OS, and project setup interact under the hood. Ensuring strict version alignment, cleaning all caches, and—if possible—building on Linux or with minimal Windows directory nesting are your best bets until the ecosystem matures further.
If you see errors like “undefined symbol: std::runtime_error::~runtime_error()” or “operator new(unsigned long),” know that you are not alone, and that these are active areas of investigation and improvement across the React Native and Android NDK communities.