Android startup retries do not restore lost adb reverse mappings
Maintainer thường phản hồi trong vòng 1 ngày
Đánh giá
- Độ khó
- 3/5
- Thời gian dự kiến
- 1-2 ngày
- Mức phù hợp với người mới
- 35/100
- Loại issue
- Lỗi
- Độ rõ ràng
- Đặc tả rõ ràng
- Mức độ hoạt động
- Đình trệ
- Công nghệ
- android, react-native, typescript
- Lĩnh vực
- testing
Hướng nghiên cứu
Read packages/platform-android/src/instance.ts, especially configureAndroidRuntime() and the emulator and physical-device session factories; then compare them with the retry flow in packages/bundler-metro/src/startup.ts. Use the attached reproducer and restore-port-forwarding.patch as evidence, and verify that startup retries restore the configured Metro forwarding and the existing 8080 mapping. A linked open pull request (#211) already addresses this work.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
Describe the bug
When the Metro adb reverse mapping disappears between test files, Android app restarts do not restore it.
Metro remains healthy on the host, but the app cannot request its bundle. All three launch attempts fail with the same startup error.
I reproduced this with two test files that each assert 1 + 1 === 2.
Neither test calls a device-info or attestation API.
After the first file passes, a Harness plugin removes only the selected emulator's Metro reverse mapping.
The next file fails before its test executes.
Recorded reproduction
Both recordings use the same emulator, APK, two trivial tests, and deliberate removal of the Metro mapping. The Android runner implementation is the only change. Test-file order varies; both files contain the same assertion.
Before: unpatched 1.6.0. The first file passes. After the mapping is removed, the next file fails after three launch attempts. Exit code 1.
20-second recording (terminal on the left, emulator on the right):
https://github.com/user-attachments/assets/2aadb076-074c-41a5-943b-f84503180fe6
After: candidate patch. Harness restores tcp:8081 before the next launch. Both files and both tests pass. Exit code 0.
13-second recording:
https://github.com/user-attachments/assets/2989da8e-39f0-4fc6-9ab6-9ebf10c4f754
The videos show the live run at normal speed. The terminal displays selected diagnostic lines with shortened paths. Screenshots are frames from these recordings. The window title is cropped out, and the videos end shortly after the results appear. The emulator and terminal were recorded concurrently and placed side by side.
Full logs from these recorded runs: unpatched, patched.
Expected: Before launching or retrying the app, restore the device-side forwarding required to reach Metro.
Actual: Harness restarts the app without recreating the missing mapping:
The app did not request its Metro bundle after 3 launch attempts within 3000ms.
Last Metro status: HTTP 200: packager-status:running. Only prewarm traffic was observed.
The error is shown on two lines here for readability. The attached log contains the original line.
bundleStartTimeout is set to 3000 ms in the reproducer to shorten failed attempts; the first app launch succeeds.
System Info
Test device: Android emulator, API 35, Google APIs, arm64-v8a.
Android Emulator: 37.2.11.0. ADB/platform-tools: 37.0.1-15733141.
The app uses Hermes and the New Architecture.
yarn react-native info output from the example workspace is below. Personal paths are redacted.
The CLI reports Android SDK: Not Found; the emulator and ADB versions above were checked directly from the installed SDK tools.
React Native environment
info Fetching system and libraries information...
System:
OS: macOS 27.0.1
CPU: (18) arm64 Apple M5 Max
Memory: 2.33 GB / 48.00 GB
Shell:
version: "5.9"
path: /bin/zsh
Binaries:
Node:
version: 22.16.0
path: <tmp>/xfs-c56faaac/node
Yarn:
version: 4.17.0
path: <tmp>/xfs-c56faaac/yarn
npm:
version: 10.9.2
path: <home>/.nvm/versions/node/v22.16.0/bin/npm
Watchman:
version: 2026.10.12.00
path: /opt/homebrew/bin/watchman
Managers:
CocoaPods:
version: 1.17.0
path: /opt/homebrew/bin/pod
SDKs:
iOS SDK:
Platforms:
- DriverKit 27.0
- iOS 27.1
- macOS 27.0
- tvOS 27.0
- visionOS 27.0
- watchOS 27.0
Android SDK: Not Found
IDEs:
Android Studio: 2026.2 AI-262.9437.185.2621.16467767
Xcode:
version: 27.1/27A9275
path: /usr/bin/xcodebuild
Languages:
Java:
version: 24.0.2
path: /usr/bin/javac
Ruby:
version: 4.0.7
path: /opt/homebrew/bin/ruby
npmPackages:
"@react-native-community/cli":
installed: 20.2.0
wanted: 20.2.0
react:
installed: 19.3.0
wanted: 19.3.0
react-native:
installed: 0.88.0
wanted: 0.88.0
react-native-macos: Not Found
npmGlobalPackages:
"*react-native*": Not Found
Android:
hermesEnabled: true
newArchEnabled: true
iOS:
hermesEnabled: true
newArchEnabled: false
React Native Harness Version
react-native-harness and @react-native-harness/platform-android: 1.6.0.
The runtime reproduction uses unpatched 1.6.0 Android runner code.
I also reviewed upstream main at 9c257af3ed5f41341235cf44bb16b6c43220395d.
Its platform-android/src/instance.ts is identical to the v1.6.0 file. I did not run the main branch.
I have not established which version first introduced this behavior.
Reproduction
Example repository at the reproduction commit.
This is an existing example app, not a standalone minimal repository.
The attachments supply two trivial test files and a launcher that selects only those files.
The repository commit includes a candidate patch, so the steps below first replace the Android runner with unpatched 1.6.0.
Steps to reproduce
Use Node 22, Yarn 4, and a configured Android build environment. Start an API 35 arm64 emulator.
Replace emulator-5554 below with its serial from adb devices.
-
Check out the example and select the unpatched Android runner:
git clone https://github.com/l2hyunwoo/react-native-nitro-device-info.git cd react-native-nitro-device-info git checkout --detach e6ab56ad9bec5d47d2285f2c5e9a0db9c2f1b11f yarn install --immutable yarn workspace react-native-nitro-device-integrity-demo add --dev @react-native-harness/[email protected] -
Build and install the debug example:
yarn workspace react-native-nitro-device-integrity prepare (cd example/integrity-demo/android && ./gradlew :app:assembleDebug -PreactNativeArchitectures=arm64-v8a) adb -s emulator-5554 install -r example/integrity-demo/android/app/build/outputs/apk/debug/app-debug.apk -
Download the three reproduction files individually from the attachments, then run the launcher. The launcher is attached as
.mjs.txtbecause GitHub rejects.mjsuploads; the command saves it with its original extension:mkdir -p evidence curl --fail --location 'https://github.com/user-attachments/files/33629490/reproduce-reverse-loss.mjs.txt' -o evidence/reproduce-reverse-loss.mjs curl --fail --location 'https://github.com/user-attachments/files/33629485/reverse-repro-a.harness.ts' -o evidence/reverse-repro-a.harness.ts curl --fail --location 'https://github.com/user-attachments/files/33629486/reverse-repro-b.harness.ts' -o evidence/reverse-repro-b.harness.ts cp evidence/reverse-repro-*.harness.ts example/integrity-demo/src/__tests__/ HARNESS_DEBUG=1 node evidence/reproduce-reverse-loss.mjs integrity-demo emulator-5554
The launcher uses resetEnvironmentBetweenTestFiles: true, selects the named emulator, and leaves maxAppRestarts at its default of 2.
After the first passing file, it removes the actual Metro port reported by the metro.initialized hook:
adb('reverse', '--remove', `tcp:${metroPort}`);
It does not kill the shared ADB server. The other emulator mappings remain in place.
Evidence
Supporting logs, reproduction files, and candidate patch
Individual attachments:
Before removal, adb reverse --list contains tcp:8081 tcp:8081 and tcp:8080 tcp:8080.
After removal, only the 8080 mapping remains.
The unpatched trace then shows three app launch attempts, but no new reverse tcp:8081 tcp:8081 command.
| Controlled run | Result |
|---|---|
| Unpatched 1.6.0, two trivial files | 1 file passed; 1 failed before executing its test |
| Candidate patch, same two files and mapping removal | 2 files passed; 2 tests passed |
| Candidate patch, integrity-demo full suite | 3/3 runs passed; 16 tests per run |
| Candidate patch, showcase full suite | 3/3 runs passed; 109 passed and 6 skipped per run |
Each full-suite run also removes the Metro mapping after its first passing file, with process resets enabled.
The full-suite regression uses the normal timeout settings. Both Metro configs omit the deprecated withRnHarness wrapper.
The attachments include complete sanitized before/after logs, the runnable reproducer, the test files, and the candidate patch.
In the patched trace, Harness restores tcp:8081 before the second launch, and the runtime connects successfully.
Suspected cause and candidate fix
configureAndroidRuntime() configures reverse mappings during platform initialization.
The emulator session factory does not repeat that setup when creating subsequent app sessions.
The physical-device factory has the same structure, but I have only tested the emulator.
The startup loop retries after a missing bundle request.
Those retries create another app session without repairing the missing mapping.
The candidate patch extracts the existing reverse setup into a helper and calls it before every app-session launch.
It restores the configured Metro port and preserves the existing 8080 forwarding behavior.
This covers process resets and startup retries without increasing timeouts or disabling test isolation.
To validate the candidate in the reproduction checkout, restore its original patched dependency and rerun:
git restore example/integrity-demo/package.json yarn.lock
yarn install --immutable
HARNESS_DEBUG=1 node evidence/reproduce-reverse-loss.mjs integrity-demo emulator-5554
Scope
An external ADB server shutdown was also observed during the investigation, interrupting an am force-stop command with exit code 255.
That is separate from this controlled reproduction, which keeps ADB running and removes one mapping.
The proposed fix handles missing forwarding on the next launch; it does not make commands immune to an ADB shutdown in progress.
I cannot attribute every earlier intermittent startup failure to this mechanism.
- Ngôn ngữ chính
- TypeScript
- Star
- 333
- Fork
- 20
- Merge trung bình
- 1 ngày 15 giờ
- Pull request đã merge (30 ngày)
- 5
Chuẩn bị môi trường
- Không có Dockerfile hay tệp Docker Compose
- Có mẫu pull request
- Đọc hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của callstackincubator/react-native-harness
-
Android runner can't start on a Windows host: SDK binaries are looked up without .exe or .batĐang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
callstackincubator/react-native-harness#201 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
callstackincubator/react-native-harness#199 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Windows Android SDK path not foundCó thể đã có người làm @V3RON đã nhận 35 ngày trước. Đang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 74/100
callstackincubator/react-native-harness#183 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
callstackincubator/react-native-harness#128 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Support SwiftPM in @react-native-harness/uiCó thể đã có người làm @mrousavy đã nhận hôm nay. Đang mở
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 35/100
callstackincubator/react-native-harness#212 ·
Maintainer thường phản hồi trong vòng 1 ngày
Tất cả issue của callstackincubator/react-native-harness
Issue tương tự
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 76/100
ccch1mneyyy/dsh-TUI#1631 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
MiniMax-AI/minimax-code#507 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 82/100
-
Transient OAuth login failure persists in getLoginStatus and masks active account in dashboardCó thể làm lại được Pull request cho issue này đã bị đóng mà không được merge. Đang mởaccount-pool bug gui
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 67/100
lidge-jun/opencodex#7378 · 2 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Admin search throws for permissions added through Admin.generalIndexItems('permissions', ...)Đang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 76/100
Maintainer thường phản hồi trong vòng 1 ngày