Skip to content

server: OpenCode Mobile 0.4.15 cannot pair with desktop service — /global/health serves SPA HTML instead of JSON #58145

Closed as duplicate

Description

@guteseele20-design

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

  1. 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 (both 0.0.0.0, reachable from the phone — the built-in diag confirms 200).
  2. 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 200 for /global/health (it seems to only check the HTTP status, not the body).
  3. Alternative attempt: paste the one-time link http://<PC-LAN-IP>:28894/auth/connect/<code> into the app's server-address field → first 401 (despite entering the correct password when asked), then 404 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/info when 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, then 404 api error. Notably, /api/health exists 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

  1. opencode-agent commented on Oct 22, 2026

    @opencode-agent
    Contributor

    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.json gets the web UI's HTML page, which is why the app hits Unexpected character: <. /api/health was removed on purpose between 2.1.2 and 2.1.3. On v2, GET /api/info with 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:

    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.

  2. guteseele20-design commented on Oct 22, 2026

    @guteseele20-design
    Author

    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 of JSON 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.

  3. neriousy commented on Oct 23, 2026

    @neriousy
    Member

    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.

  4. opencode-agent commented on Oct 23, 2026

    @opencode-agent
    Contributor

    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/info with 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!

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions