Skip to content

fix: handle null libc version on Android/Termux#305

Open
zerone0x wants to merge 1 commit intogoogleworkspace:mainfrom
zerone0x:fix/libc-null-version-crash
Open

fix: handle null libc version on Android/Termux#305
zerone0x wants to merge 1 commit intogoogleworkspace:mainfrom
zerone0x:fix/libc-null-version-crash

Conversation

@zerone0x
Copy link
Contributor

@zerone0x zerone0x commented Mar 8, 2026

Summary

  • Fixes crash on Android/Termux where detect-libc returns null for the libc version (bionic libc), causing binary.js to throw TypeError: Cannot read properties of null (reading 'split')
  • Adds a null check for libcVersion in the npm installer's binary.js, falling back to the static musl binary when the libc version cannot be detected
  • Patches the cargo-dist-generated npm package during the release build via a new workflow step

Details

On Android/Termux with bionic libc:

  1. libc.familySync() does not return "musl"
  2. libc.isNonGlibcLinuxSync() returns false
  3. libc.versionSync() returns null
  4. Calling .split(".") on null crashes the CLI

The fix adds a null guard before the .split() call. When libcVersion is null, the installer logs a warning and falls back to the static musl binary, matching the existing behavior for other incompatible libc scenarios.

Since binary.js is generated by cargo-dist, the patched version is stored in npm/binary.js and applied to the npm tarball during the build-global-artifacts step of the release workflow.

Fixes #271

Test plan

  • All existing Rust tests pass (426 tests)
  • binary.js passes Node.js syntax check (node --check)
  • Verify on Android/Termux that gws no longer crashes with null libc version

🤖 Generated with Claude Code

On Android/Termux with bionic libc, detect-libc returns null for the
libc version. The npm installer's binary.js crashes with
"Cannot read properties of null (reading 'split')" because it calls
.split(".") on the null return value without a null check.

This adds a null check for libcVersion in binary.js and falls back to
the static musl binary when the libc version cannot be detected. The
patched binary.js is applied to the npm package during the release
build via a new step in the release workflow.

Fixes googleworkspace#271

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@changeset-bot
Copy link

changeset-bot bot commented Mar 8, 2026

⚠️ No Changeset found

Latest commit: 3e7b7e8

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request enhances the robustness of the npm installer by addressing a critical issue on Android/Termux systems where the libc version could not be reliably determined. The changes prevent application crashes by introducing a null-safe check for libc version detection and implementing a fallback mechanism to a static musl binary, ensuring broader compatibility and stability for users on diverse Linux-based platforms.

Highlights

  • Crash Fix for Android/Termux: Resolved a crash occurring on Android/Termux environments where detect-libc returns null for the libc version, which previously caused a TypeError when attempting to call .split() on null.
  • Robust Libc Version Detection: Implemented a null check for the libcVersion in the npm installer's binary.js script. If the libc version cannot be detected, the installer now gracefully falls back to using a static musl binary.
  • Automated Patching in Release Workflow: Integrated a new workflow step to patch the cargo-dist-generated npm package during the release build process, ensuring the fix is applied to distributed artifacts.
Changelog
  • npm/binary.js
    • Added a null check for the libc.versionSync() return value to prevent crashes when the libc version is undetectable (e.g., bionic libc on Android/Termux).
    • Implemented a fallback mechanism to use the unknown-linux-musl-static target when the libc version cannot be determined or is incompatible with the builder's glibc minimum requirements.
Ignored Files
  • Ignored by pattern: .github/workflows/** (1)
    • .github/workflows/release.yml
Activity
  • All 426 existing Rust tests passed.
  • The binary.js file successfully passed Node.js syntax checks (node --check).
  • Verification is pending on Android/Termux to confirm that gws no longer crashes with a null libc version.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Generative AI Prohibited Use Policy, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@google-cla
Copy link

google-cla bot commented Mar 8, 2026

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request correctly fixes a crash that occurs on Android/Termux when the libc version cannot be determined. The fix involves adding a null check and falling back to a static musl binary, which is a sound approach. I have provided a few comments on the newly added npm/binary.js file to enhance its robustness and reliability.

} = require("./package.json");

// FIXME: implement NPM installer handling of fallback download URLs
const artifactDownloadUrl = artifactDownloadUrls[0];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The installer only uses the first URL from artifactDownloadUrls, which makes it vulnerable to failures if that specific URL is down. The FIXME comment acknowledges this. To improve reliability, the installer should be updated to try all available fallback URLs in artifactDownloadUrls until a binary is successfully downloaded.

}

if (rawOsType === "Linux") {
if (libc.familySync() == "musl") {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

It's best practice to use the strict equality operator (===) for comparisons to avoid unexpected type coercion. This prevents potential bugs and makes the code's intent clearer.

Suggested change
if (libc.familySync() == "musl") {
if (libc.familySync() === "musl") {

Comment on lines +71 to +76
let splitLibcVersion = libcVersion.split(".");
let libcMajorVersion = splitLibcVersion[0];
let libcMinorVersion = splitLibcVersion[1];
if (
libcMajorVersion != builderGlibcMajorVersion ||
libcMinorVersion < builderGlibcMinorVersion
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The version components obtained from split('.') are strings. Comparing them directly with numbers relies on implicit type coercion, which can be fragile and lead to bugs (e.g., lexicographical string comparison like '10' < '2' is true). It's safer and clearer to explicitly parse the version components into integers before performing numerical comparisons. This makes the logic more robust.

        const [majorStr, minorStr] = libcVersion.split(".");
        const libcMajorVersion = parseInt(majorStr, 10);
        const libcMinorVersion = parseInt(minorStr, 10);
        if (
          libcMajorVersion !== builderGlibcMajorVersion ||
          libcMinorVersion < builderGlibcMinorVersion
        )

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

gws crashes on Termux due to libc detection (split on null)

2 participants