Skip to content

v1 SDK calls get the web UI's HTML with 200 from a v2 server, so old integrations fail silently #63598

Closed as duplicate

Description

@Yahhi

Description

The migrate-v1 guide says V1 integrations must move to @opencode/client. This issue is about how they fail when they don't: silently.

Against an OpenCode 2 server, the v1 client in @opencode-ai/sdk (1.19.5, still the npm latest) doesn't fail. GET /session answers 200 with the web UI's HTML (also with Accept: application/json), so client.session.list() returns that page as data. POST /session answers 405, which the SDK hands back as {"error":{}} without throwing. An integration written for v1 keeps running and does nothing.

I measured this with coding agents. A real 2.2.7 server was running, and I asked Claude Code, Codex and Gemini (2 runs each) for a small script with "the official OpenCode JavaScript SDK or client from npm": create a session and list session titles. 3 of the 6 runs started with @opencode-ai/sdk. Claude noticed the HTML only because a live server was there to test against. It then switched to client.v2.* in the same package and passed the title through $body_title, because those types have no title field. Codex found @opencode/client via opencode.ai/docs. Without a server to test against, the v1 version would have shipped and returned [].

Related: #55705 asks for an API version in /api/info so clients can detect a v2 server. This is the other side of the same mismatch: what the server answers on the old paths.

Two changes would make this loud:

  • answer the old API paths with a JSON 404 or 410 that names @opencode/client when the request asks for JSON, instead of the web UI;
  • a pointer to @opencode/client on the @opencode-ai/sdk npm page (README or npm deprecate message).

OpenCode version

server: @opencode/cli 2.2.7 (opencode serve); client: @opencode-ai/sdk 1.19.5

Steps to reproduce

  1. OPENCODE_PASSWORD=pw opencode serve --port 4096 (2.2.7)
  2. import { createOpencodeClient } from "@opencode-ai/sdk"
    const client = createOpencodeClient({ baseUrl: "http://127.0.0.1:4096",
      headers: { Authorization: "Basic " + Buffer.from("opencode:pw").toString("base64") } })
    console.log(await client.session.create({ body: { title: "x" } }))  // server 405 -> { error: {}, ... }, no throw
    console.log((await client.session.list()).data.slice(0, 40))        // "<!doctype html>..."
  3. With @opencode/client (OpenCode.make(...).session.create/list) the same server works.

Operating System

macOS 15 (Darwin 24.6), Node 24


I research how coding agents use dev tools: dev.to/yahhi · [email protected]

Activity

  1. opencodejr commented on Nov 12, 2026

    @opencodejr
    Contributor

    Thanks for the measurements and the clear reproduction, @Yahhi.

    I think this is a duplicate of #55704. That issue reports that a v2 server sends back the web UI's HTML with a 200 for paths that have no route, including the v1 API paths, and asks for a JSON 404 for requests that don't want HTML. That's the server-side change you propose.

    In packages/cli/src/services/web-ui.ts, only /api, /api/*, /auth/* and /openapi.json go to the API; every other path gets the web app, and the Accept header isn't checked there. That's why GET /session returns the HTML page and POST /session returns 405. A contributor has posted a detailed Accept-negotiation proposal in #55704 for maintainers to review.

    Until then, as suggested in #55704, clients can check GET /api/info to detect a v2 server.

    Related issues, ordered from most to least likely to cover this:

    I'm closing this issue now as a duplicate of #55704. Please add your details there, especially the coding-agent measurements and the suggested npm deprecate pointer for @opencode-ai/sdk, which #55704 doesn't cover yet. If you think this isn't the same problem, reply here and the issue will reopen.

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