Repository navigation
[Bug]: Android manual pairing rejects formatted codes and can report a false timeout #4889
Description
Before submitting
- I searched existing issues and did not find a duplicate.
- I included enough detail to reproduce or investigate the problem.
Area
apps/mobile (not currently listed in the issue template's Area options)
Steps to reproduce
- Run a headless T3 server and expose it through Tailscale Serve HTTPS.
- Create a one-time pairing credential. The CLI emits an uppercase, unhyphenated 12-character value.
- In the official Android app, open Add Environment.
- Enter the reachable HTTPS backend in Host.
- Enter the credential in the hyphenated format suggested by the field placeholder (for example,
XXXX-XXXX-XXXX). - Tap Add environment.
- Retry with the raw unhyphenated code.
- As a control, paste the complete
https://<host>/pair#token=<raw-token>URL into Host, leave Pairing code empty, and submit.
Expected behavior
The manual pairing-code path should work reliably.
Either:
- normalize presentation separators/whitespace and case before exchange, or
- show the exact server-generated format and clearly require it.
The surfaced error should also match the actual failed request.
Actual behavior
- Hyphenated manual entry is sent verbatim and the server returns
401 auth_invalid. - A retry with raw code also failed during this reproduction.
- The app subsequently reported a timeout after
10000ms, despite the corresponding server-side/oauth/tokenrequest returning401in approximately 2.7ms. - Pasting the complete pairing URL into Host with Pairing code empty succeeded immediately.
The backend and transport were independently verified: environment discovery returned 200, Tailscale connectivity was healthy, and a disposable server-generated credential exchanged successfully through the same public HTTPS /oauth/token endpoint.
Impact
Major degradation or frequent failure.
The advertised manual host + pairing-code flow is unreliable. QR/full-URL pairing remains a workaround.
Version or commit
- Server:
t3 v0.0.32-nightly.20260729.951 - Mobile: official Android client installed from Google Play on 2026-07-29
Environment
- Device: Pixel 9a
- Client OS: Android
- Server OS: Linux x64
- Transport: Tailscale Serve HTTPS on port 443
- Mobile HTTP user agent observed server-side:
okhttp/4.9.2
Logs or stack traces
GET /.well-known/t3/environment -> 200
POST /oauth/token -> 401 (about 2.7ms)
Mobile UI -> timed out after 10000ms
Control:
POST /oauth/token with a disposable server-generated credential through
the same Tailscale HTTPS endpoint -> 200
Secrets, pairing credentials, environment IDs, trace IDs, and Tailnet hostnames have been omitted.
Relevant source observation
The Android pairing field currently shows the placeholder abc-123-xyz, while buildPairingUrl() only applies .trim() to the code before putting it into the URL fragment. It does not remove presentation separators or normalize case.
Relevant files:
apps/mobile/src/features/connection/ConnectionsNewRouteScreen.tsxapps/mobile/src/features/connection/pairing.ts
Workaround
Paste the complete server-generated /pair#token=... URL into the Host field, leave Pairing code empty, then add the environment. Scanning the server-generated QR code should follow the same successful path.
Activity
maria-rcks commentedon Oct 9, 2026
Note
This is an automated response from a bot acting on maria's behalf.
This issue has had no activity since 2026-07-30.
Is it still relevant on the current version? If so, your version and OS would help.
mixinDennisBarzanoffMixin commentedon Oct 16, 2026
+1
juliusmarminge commentedon Oct 22, 2026
Inspected current main at 89fe509232. The manual pairing helper still only trims the credential before putting it in the token fragment; the field placeholder is now “Pairing code”, so the old formatting hint has changed. The reported Android 401-to-timeout behavior has not been reproduced. Further investigation and a fix require review of pairing credential handling and the authorization request path, which are outside this automated triage run’s allowed fix scope. Leaving open for maintainer review; no fix PR created.
juliusmarminge commentedon Oct 22, 2026
Existing work check: #22089 is open and explicitly addresses this issue’s letter-case problem only; separators and the false timeout remain outside its scope. #22910 addresses stale Code overriding a pasted URL on mobile, a different symptom. Scanned all 938 open issues and 1,382 open PRs; no duplicate issue or complete fix found. No competing PR created.