Repository navigation
Description
Summary
OpenCode Mobile (Android, 0.4.15) cannot connect to the shared background service on desktop (Windows) — tested with server v2.1.2 and again after updating the desktop app to v2.1.3. The manual "Add Connection" flow fails with Connection Failed — Error: JSON Parse error: Unexpected character: <: the app appears to expect a JSON health response, while the Windows desktop service serves the web UI SPA shell at /global/health (200 text/html). Opening the same server's one-time pair link (opencode pair) in the phone's browser works perfectly (full web UI, 30-day session), so reachability and auth are not the problem — it is a client/server contract mismatch.
Environment
- opencode version: desktop service v2.1.2 (tested) → v2.1.3 after desktop auto-update (tested, latest channel); OpenCode Mobile 0.4.15 (release
opencode-mobile@0.4.15) - OS: Windows_NT 10.0.26200 (win32 x64), OpenCode desktop app → background service
- Terminal: n/a (desktop app bundle; CLI probes from PowerShell 5.1)
- Shell: PowerShell 5.1 / cmd
- Install/channel: latest (desktop bundle)
- Active plugins: none
Reproduction
- Desktop:
opencode service set hostname 0.0.0.0, set a password,opencode service start. v2.1.2 listened on:45278; after the desktop auto-update, v2.1.3 on:28894(both0.0.0.0, reachable from the phone — the built-in diag confirms 200). - Phone → OpenCode Mobile → Add Connection → LAN IP of the PC + port + the password set on the server → Connect.
- Result:
Connection Failed ... Error: JSON Parse error: Unexpected character: < - The app's own diagnostic reports
OK 200for/global/health(it seems to only check the HTTP status, not the body).
- Result:
- Alternative attempt: paste the one-time link
http://<PC-LAN-IP>:28894/auth/connect/<code>into the app's server-address field → first401(despite entering the correct password when asked), then404 api error.
Expected Behavior
- Manual add (address + password): the health check should succeed and the app should connect. Basic auth
Authorization: Basic base64("opencode:<password>")returns 200 JSON on/api/infowhen probed with curl, so credentials are valid. - Pasted pair link: the app should consume
/auth/connect/<code>and connect the same way the browser does (as documented).
Actual Behavior
- Manual add: JSON parse error on an HTML body —
Unexpected character: <. - Pasted pair link:
401, then404 api error. Notably,/api/healthexists in v2.1.2 as an auth-gated route (unauthenticated → 401 + JSON{"_tag":"UnauthorizedError"}) but is gone in v2.1.3 (404).
Additional Context
Probes against both server builds (fetch from the LAN host):
| Request | Server v2.1.2 | Server v2.1.3 |
|---|---|---|
GET /global/health |
200 text/html (SPA shell), same with Accept: application/json and with Basic auth |
200 text/html (same) |
GET /health, /global/healthz, /global/info |
200 text/html |
200 text/html |
GET /api/info + Basic opencode:<password> |
200 JSON (version, pid, urls) | 200 JSON |
GET /api/info unauth |
401 JSON | 401 JSON |
GET /api/health unauth |
401 JSON (route exists, auth-gated) | 404 (route absent) |
GET /openapi.json + Basic |
— (401) | 200; 121 paths, no health path anywhere (no JSON /global/health, no /api/health) |
| Bearer-style auth | 401 always | 401 always |
The server self-reports its LAN URL via /api/info (urls: ["http://127.0.0.1:28894", "http://<PC-LAN-IP>:28894", ...]), so the intended external address matches what the app is given.
Conclusion: OpenCode Mobile 0.4.15 seems written against a server contract the current desktop bundles don't implement (a JSON health endpoint at /global/health and/or /api/health). Manual add-server fails on any desktop build we can obtain (v2.1.2 and v2.1.3 both fail).
Workaround that works today: opencode pair → open the printed LAN link in the phone browser → full web UI, 30-day session. Only the Android app remains unusable in this combination.
Activity
opencode-agent commentedon Oct 22, 2026
Thanks for the detailed probes, @guteseele20-design!
I think this is a duplicate of #55704.
Some background: OpenCode Mobile isn't built by the OpenCode team. The README lists "opencode-mobile" as an example of an unaffiliated project. It seems to be written against the v1 HTTP API, which had
/global/health. v2 servers don't have that route. Any path outside/api/*,/auth/*and/openapi.jsongets the web UI's HTML page, which is why the app hitsUnexpected character: <./api/healthwas removed on purpose between 2.1.2 and 2.1.3. On v2,GET /api/infowith Basic auth is the health check (it's the one returning JSON in your probes). The pair-link failure looks like the same mismatch: the app doesn't handle v2's/auth/connect/<code>flow. So the app itself would need updating for v2, and that's best raised with its maintainers.Possible duplicates and related issues, ordered by likelihood:
/global/healthand other non-API routes return 200 HTML instead of a 404, which breaks third-party clients written for v1. This is the same server behaviour you're seeing./api/info, so clients like this one can detect a v2 server and show a clear error./global/healthreturns HTML symptom from another client (closed).The pair link in the phone's browser, which you already found, works on v2.
The bot will close this issue as a duplicate in 1 day unless you reply explaining how your problem is different.
guteseele20-design commentedon Oct 22, 2026
Thanks for the quick and thorough triage! Closing as a duplicate of #55704 is fine for the server-side behaviour.
One extra data point that may support #55705: the mobile app's diagnostic only checks the HTTP status of
/global/health— it reports "OK 200" against a pure SPA HTML body — so a status-only health check masks the v1/v2 mismatch client-side. With a version/intent field in/api/info(or a JSON 404 for non-API routes), a client could show a clear "server speaks a different API version" message instead ofJSON Parse error: Unexpected character: <.Also reproduced the pair-link flow failing inside the app (401 after entering the password, then "404 api error"), consistent with the app not handling v2's
/auth/connect/<code>flow. I'll raise that with the app's maintainers.For the record, the workaround works well:
opencode pair→ open the LAN link in the phone's browser → full v2 web UI, 30-day session.neriousy commentedon Oct 23, 2026
Closing as a duplicate of #55704, which tracks the unexpected SPA HTML response from unknown non-API routes. The status-only health-check diagnostic has been transferred there; the mobile app’s pairing-flow changes remain with its maintainers.
opencode-agent commentedon Oct 23, 2026
Closing this as a duplicate of #55704. There has been no reply in the past day explaining how this problem is different.
In short, OpenCode Mobile is a third-party app written against the v1 API. v2 servers don't have
/global/health, so that path returns the web UI's HTML instead. On v2,GET /api/infowith Basic auth is the health check. The app needs updating for v2, which is best raised with its maintainers. Opening the pair link in your phone's browser works in the meantime.To follow progress, see #55704 and the related request #55705, which would let clients detect a v2 server. If your problem turns out to be something else, comment here and we'll take another look. Thanks again for the thorough report!