Skip to content

Session headers X-Session-Id, x-session-affinity, x-parent-session-id no longer sent on LLM requests: silent regression of #20744 / #31511 in the v2 session runner #42694

Description

@MacJedi42

Summary

OpenCode used to stamp x-session-affinity, X-Session-Id and (for subagent child sessions) x-parent-session-id on every outbound LLM provider request, so proxies and gateways could correlate calls per session. That behaviour shipped in #20744 (April) and #31511 (June), and was still confirmed working by a user in late July (#39912: "I confirmed both headers reach the server").

In current releases ( i personally verified on v1.18.16 and v1.18.18) the headers are gone. No session header of any kind seems to reach the provider endpoint. The header-stamping code still exists in the repo (packages/opencode/src/session/llm/request.ts), and is even still present in the compiled release binary, but requests are now built by the v2 session runner (packages/core/src/session/runner/), which has no equivalent.

Environment

  • opencode version: 1.18.16 and 1.18.18
  • Mode: headless opencode serve --hostname 0.0.0.0 --port 4096, driven over the HTTP API
  • OS: Debian
  • Provider under test: anthropic with a custom baseURL in opencode.json (the proxy/gateway pattern the headers exist for); no special flags, OPENCODE_EXPERIMENTAL_NATIVE_LLM unset

Plugins

No response

OpenCode version

1.18.18

Steps to reproduce

  1. Start a header-echo "provider" that logs request headers and answers with minimal valid Anthropic SSE:
// echo-upstream.ts — bun run echo-upstream.ts
const SSE =
  'event: message_start\ndata: {"type":"message_start","message":{"id":"m1","type":"message","role":"assistant","content":[],"model":"claude-sonnet-5","usage":{"input_tokens":1,"output_tokens":1}}}\n\n' +
  'event: content_block_start\ndata: {"type":"content_block_start","index":0,"content_block":{"type":"text","text":""}}\n\n' +
  'event: content_block_delta\ndata: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"ok"}}\n\n' +
  'event: content_block_stop\ndata: {"type":"content_block_stop","index":0}\n\n' +
  'event: message_delta\ndata: {"type":"message_delta","delta":{"stop_reason":"end_turn"},"usage":{"output_tokens":2}}\n\n' +
  'event: message_stop\ndata: {"type":"message_stop"}\n\n';
Bun.serve({
  port: 18099,
  fetch(req) {
    console.log(JSON.stringify({
      path: new URL(req.url).pathname,
      headerNames: [...req.headers.keys()].sort(),
      xSessionId: req.headers.get("x-session-id"),
      xSessionAffinity: req.headers.get("x-session-affinity"),
    }));
    return new Response(SSE, { status: 200, headers: { "content-type": "text/event-stream" } });
  },
});
  1. Point opencode at it via ~/.config/opencode/opencode.json :
{
  "model": "anthropic/claude-sonnet-5",
  "provider": {
    "anthropic": {
      "npm": "@ai-sdk/anthropic",
      "options": { "baseURL": "http://localhost:18099/v1", "apiKey": "dummy" }
    }
  }
}
  1. Run ANTHROPIC_API_KEY=dummy opencode serve --port 4096 , then drive one prompt over the API. (The per-session model pin matters: the top-level model key in opencode.json is not applied to API-created sessions, which otherwise fall through to a default provider.)
SID=$(curl -s -X POST -H "content-type: application/json" -d '{}' http://localhost:4096/session | jq -r .id)
curl -s -X POST -H "content-type: application/json" \
  -d '{"model":{"providerID":"anthropic","id":"claude-sonnet-5"}}' \
  "http://localhost:4096/api/session/$SID/model"
curl -s -X POST -H "content-type: application/json" \
  -d '{"prompt":{"text":"say ok"}}' "http://localhost:4096/api/session/$SID/prompt"
  1. The echo server logs the full header set of the LLM request:
{"path":"/v1/messages",
 "headerNames":["accept","accept-encoding","anthropic-beta","anthropic-version","b3","connection","content-length","content-type","host","traceparent","user-agent","x-api-key"],
 "xSessionId":null,"xSessionAffinity":null}

The following are missing: x-session-affinity, X-Session-Id, x-parent-session-id.

Screenshot and/or share link

No response

Operating System

Debian 13 (Trixie)

Terminal

No response

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions