Skip to content

fix(tirith): skip auto-install on Termux native (Bionic libc) - #26281

Closed
briandevans wants to merge 1 commit into
NousResearch:mainfrom
briandevans:fix/tirith-termux-native-skip-26275
Closed

fix(tirith): skip auto-install on Termux native (Bionic libc)#26281
briandevans wants to merge 1 commit into
NousResearch:mainfrom
briandevans:fix/tirith-termux-native-skip-26275

Conversation

@briandevans

Copy link
Copy Markdown
Contributor

Summary

  • Detect Termux native (PREFIX=/data/data/com.termux/files/...) in _detect_target() and short-circuit to None so the linux-gnu binaries — whose dynamic interpreter /lib/ld-linux-*.so.* doesn't exist on Termux's Bionic-libc filesystem — are never downloaded.
  • Surface a distinct termux_native_unsupported reason from _install_tirith() plus an actionable INFO log pointing the user at proot Ubuntu or TIRITH_ENABLED=false.
  • 7 focused regression tests covering true/false detection, the Termux/Android system-string variants, the proot-Ubuntu pass-through, and the install-side reason tag.

Fixes #26275.

The bug

Issue #26275: hermes-agent on Termux for Android 26 (aarch64) emits

WARNING tools.tirith_security: tirith spawn failed: [Errno 2] No such file or directory: '/data/data/com.termux/files/home/.hermes/profiles/vira/bin/tirith'

— even though the binary file is present at the path. The reporter pinned this down via file tirith:

tirith: ELF 64-bit LSB pie executable, ARM aarch64, ... interpreter /lib/ld-linux-aarch64.so.1, ...

The kernel can't load /lib/ld-linux-aarch64.so.1 (Termux has no /lib at all — its filesystem lives entirely under /data/data/com.termux/files/usr/), so it returns ENOENT for the interpreter, which Python surfaces as a FileNotFoundError whose path attribute is the binary's path, not the interpreter's. The error message is misleading; the binary is fine, the dynamic linker is missing.

The auto-installer downloaded that broken binary because commit 99af222ec (fix(tirith): detect Android/Termux as Linux ABI-compatible) opted Android into the unknown-linux-gnu Rust target on the assumption that Bionic is ABI-compatible with glibc. It isn't, for any binary that's dynamically linked against glibc — the prebuilt tirith ELF embeds a glibc dynamic interpreter path that Termux can't satisfy.

The fix

Narrow the Linux/Android branch in _detect_target() to skip Termux native, detected via PREFIX=/data/data/com.termux/files/... (Termux's canonical env var, set by every Termux session). Inside a proot Ubuntu chroot on top of Termux, PREFIX is rewritten to the chroot's /usr and a real glibc is available, so that path is unaffected — verified by test_detect_target_proot_ubuntu_inside_termux_still_works.

_install_tirith() returns a distinct termux_native_unsupported reason so the disk failure marker is specific (rather than the generic unsupported_platform tag), and emits an INFO log telling the user the actual cause and three workarounds:

tirith auto-install: Termux native (Bionic libc) is unsupported;
the linux-gnu binary's dynamic interpreter (/lib/ld-linux-*.so.*) is not
present on Termux. Run inside a proot Ubuntu chroot, install tirith
manually, or set TIRITH_ENABLED=false.

A Conda-style PREFIX (e.g. /opt/conda/envs/dev) would NOT match — the prefix-string check is anchored at /data/data/com.termux/files/, verified by test_is_termux_native_false_for_unrelated_prefix.

Test plan

  • Focused regression tests: tests/tools/test_tirith_security.py::TestTermuxNativeSkip — 7/7 pass
  • Adjacent suite: tests/tools/test_tirith_security.py — 70/70 pass; tests/tools/test_command_guards.py tests/tools/test_yolo_mode.py — 38/38 pass
  • Regression guard: with tools/tirith_security.py reverted via git stash, test_detect_target_returns_none_on_termux_native fails with AssertionError: assert 'aarch64-unknown-linux-gnu' is None, demonstrating the exact bug path from the issue. Restored fix → passes.

Related

Copilot AI review requested due to automatic review settings May 15, 2026 10:19
@alt-glitch alt-glitch added type/bug Something isn't working comp/tools Tool registry, model_tools, toolsets P3 Low — cosmetic, nice to have labels May 15, 2026
@ygd58

ygd58 commented May 15, 2026

Copy link
Copy Markdown
Contributor

LGTM — dedicated _is_termux_native() helper and 7 regression tests make this the right approach. Closing my duplicate #26282 in favor of this PR.

NishantEC

This comment was marked as outdated.

@briandevans

Copy link
Copy Markdown
Contributor Author

CI audit — all 3 Tests failures are pre-existing baselines on clean origin/main (db84a78). Zero failures are in touched code.

Test Symptom Root cause on main
tests/run_agent/test_provider_parity.py::TestDeveloperRoleSwap::test_developer_role_via_nous_portal ValueError: Model has a context window of 15,000 tokens Test instantiates Nous Portal with empty model=; fallback resolves to a 15,000-token context which trips the 64K minimum guard at run_agent.py:2349.
TestBuildApiKwargsNousPortal::test_includes_nous_product_tags (same) (same)
TestBuildApiKwargsNousPortal::test_uses_chat_completions_format (same) (same)

Reproduces locally on clean main; already being addressed by #26048. The e2e failure is similarly post-#25957 baseline, also covered by #26048.

@briandevans
briandevans force-pushed the fix/tirith-termux-native-skip-26275 branch from f12ab62 to efac340 Compare May 19, 2026 03:46
@briandevans
briandevans force-pushed the fix/tirith-termux-native-skip-26275 branch 4 times, most recently from 44dc682 to f03770f Compare May 29, 2026 00:11
Issue NousResearch#26275: hermes-agent on Termux for Android emits
`tirith spawn failed: [Errno 2] No such file or directory:
'/data/data/com.termux/files/home/.hermes/profiles/X/bin/tirith'`
even though the binary file is present at the path.

The OSError is misleading: the binary exists, but the dynamic interpreter
embedded in its ELF header (`/lib/ld-linux-aarch64.so.1`, or x86_64
equivalent) does not — Termux ships Bionic libc under
`/data/data/com.termux/files/usr/` and has no `/lib` at all. The kernel
returns ENOENT for the missing interpreter, which Python surfaces as a
FileNotFoundError pointing at the binary. So the auto-installer
(99af222, "fix(tirith): detect Android/Termux as Linux ABI-compatible")
happily downloads `tirith-aarch64-unknown-linux-gnu.tar.gz` and writes a
binary that can never run.

Narrow the Linux/Android branch in `_detect_target()` to skip Termux
native, detected via `PREFIX=/data/data/com.termux/files/...` (the
canonical Termux env var). Inside a proot Ubuntu chroot on Termux, PREFIX
is rewritten to the chroot's `/usr` and a real glibc is available, so
that path is unaffected. `_install_tirith()` returns a distinct
`termux_native_unsupported` reason and logs an actionable INFO line
pointing the user at proot Ubuntu or `TIRITH_ENABLED=false`.

Regression guard: with the production change reverted, the new
`test_detect_target_returns_none_on_termux_native` test fails with
`AssertionError: assert 'aarch64-unknown-linux-gnu' is None`,
demonstrating the exact bug path from the issue.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@briandevans
briandevans force-pushed the fix/tirith-termux-native-skip-26275 branch from f03770f to e8ed9e1 Compare May 30, 2026 02:30
@briandevans

Copy link
Copy Markdown
Contributor Author

Housekeeping: closing to keep my open-PR set focused on actively-reviewed work. This has been open ~17d without maintainer review and the surrounding code has continued to move, so it's unlikely to land as-is. The underlying fix still stands — happy to reopen and rebase if it would be useful. Thanks!

@briandevans briandevans closed this Jun 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/tools Tool registry, model_tools, toolsets P3 Low — cosmetic, nice to have type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug: tirith spawn failed: [Errno 2] No such file or directory on Termux (Android)

4 participants