You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
V2: Unrelated sessions share one outbound trace ID until the server restarts #54555
In OpenCode v2.0.26, model requests from unrelated sessions connected to the same shared background server send traceparent headers with the same trace ID. Their parent-span IDs differ. An OpenTelemetry-aware LiteLLM proxy consequently records requests from multiple OpenCode sessions in one trace.
Restarting the OpenCode server changes the trace ID—even for a continuing session. Session-ID propagation works correctly. This reproduces with no local user plugins active.
Expected behavior
Unrelated session work should not inherit a server-lifetime trace. Whether trace boundaries are per request, turn, or session, restarting the server should not determine the trace ID shared by subsequent sessions.
Observability: LiteLLM proxy exporting OpenTelemetry traces to Langfuse
Plugins
No response
OpenCode version
v2.0.26
Steps to reproduce
Configure an OpenAI-compatible provider through a proxy that can inspect incoming traceparent headers.
Using the shared OpenCode service, send a model request from each of two new sessions.
Compare the headers. In my test, both requests had trace ID b40f5ce0220bde39bc9c6b1677dd9b9b, but different parent-span IDs: ada5fb70cf80e1a0 and 4512ad72886fcf3b.
Run opencode service restart and send another request. Requests from an existing session and a new session now share a different trace ID: f2ce22c33feca38d69acc7b26d540cf5.
Thanks for the detailed report, I was able to reproduce this.
I set up an OpenAI-compatible provider pointing at a local endpoint that logs the incoming traceparent and x-session-id headers, and used it on v2.0.26:
Two new sessions run through the shared background service sent requests with the same trace ID and different parent span IDs.
After opencode service restart, both a continued session and a new session switched together to a new shared trace ID.
It still happens on the latest dev (d21b079), run from source. The script below reproduces it. Session ID headers were correct throughout, as you said.
Your guess about the cause looks plausible: the session run coordinator creates its fork runtime while services are booting, so session runs may inherit the server startup span. This isn't confirmed yet.
Related: #49038 (outbound traceparent propagation) and #37395 (an earlier fix isolating per-request server traces).
Reproduction script (repro.sh)
#!/usr/bin/env bash# Reproduces #54555: unrelated sessions on the shared background service send the# same traceparent trace ID until the service restarts.# Usage: bash repro.sh (uses `opencode` from PATH)# OC_DEV=/path/to/checkout bash repro.sh (runs from source)set -u
DIR=$(mktemp -d); PROJ=$DIR/proj; mkdir -p $PROJ;export HOME=$DIR/home; mkdir -p $HOME
PORT=4599
cat >$DIR/fake.ts <<'EOF'Bun.serve({ port: Number(process.env.PORT), async fetch(req) { console.log(JSON.stringify({ traceparent: req.headers.get("traceparent"), session: req.headers.get("x-session-id") })) const body: any = await req.json().catch(() => ({})) if (!body.stream) return Response.json({ id: "x", object: "chat.completion", created: 0, model: "m", choices: [{ index: 0, message: { role: "assistant", content: "ok" }, finish_reason: "stop" }] }) const chunks = [ { id: "x", object: "chat.completion.chunk", created: 0, model: "m", choices: [{ index: 0, delta: { role: "assistant", content: "ok" }, finish_reason: null }] }, { id: "x", object: "chat.completion.chunk", created: 0, model: "m", choices: [{ index: 0, delta: {}, finish_reason: "stop" }], usage: { prompt_tokens: 1, completion_tokens: 1, total_tokens: 2 } }, ] return new Response(chunks.map(c => `data: ${JSON.stringify(c)}\n\n`).join("") + "data: [DONE]\n\n", { headers: { "content-type": "text/event-stream" } })}})EOF
cat >$PROJ/opencode.json <<EOF{ "provider": { "fake": { "npm": "@ai-sdk/openai-compatible", "name": "Fake", "options": { "baseURL": "http://127.0.0.1:$PORT/v1", "apiKey": "x" }, "models": { "m": { "name": "m" } } } }, "model": "fake/m", "small_model": "fake/m" }EOF
PORT=$PORT bun $DIR/fake.ts >$DIR/requests.log 2>&1& FAKE=$!
sleep 1
# From source the background service cannot be auto-spawned, so run one server# process by hand and point every client at it with --server.export OPENCODE_SERVER_PASSWORD=repro OPENCODE_PASSWORD=repro
start_srv() { (cd $OC_DEV/packages/cli &&exec bun run src/index.ts serve --hostname 127.0.0.1 --port 4700 >$DIR/srv.log 2>&1) & SRV=$!; sleep 8; }
oc() {
if [ -n"${OC_DEV:-}" ];thencase"$1"in
service) kill$SRV2>/dev/null;wait$SRV2>/dev/null; [ "$2"= restart ] && start_srv;return;;
run) shift;set -- run --server http://127.0.0.1:4700 "$@";;
esac
bun --conditions=browser --preload=$OC_DEV/packages/tui/node_modules/@opentui/solid/scripts/preload.js $OC_DEV/packages/cli/src/index.ts "$@"else opencode "$@";fi
}
[ -n"${OC_DEV:-}" ] && start_srv
cd$PROJ
oc run -m fake/m "session one">/dev/null 2>&1
oc run -m fake/m "session two">/dev/null 2>&1echo"== before restart (two new sessions) =="; cat $DIR/requests.log;:>$DIR/requests.log
oc service restart >/dev/null 2>&1
oc run -m fake/m -c "continue session two">/dev/null 2>&1
oc run -m fake/m "session three">/dev/null 2>&1echo"== after restart (continued session + new session) =="; cat $DIR/requests.log
oc service stop >/dev/null 2>&1kill$FAKE
Activity
opencode-agent commentedon Oct 11, 2026
Thanks for the detailed report, I was able to reproduce this.
I set up an OpenAI-compatible provider pointing at a local endpoint that logs the incoming
traceparentandx-session-idheaders, and used it on v2.0.26:opencode service restart, both a continued session and a new session switched together to a new shared trace ID.It still happens on the latest
dev(d21b079), run from source. The script below reproduces it. Session ID headers were correct throughout, as you said.Your guess about the cause looks plausible: the session run coordinator creates its fork runtime while services are booting, so session runs may inherit the server startup span. This isn't confirmed yet.
Related: #49038 (outbound
traceparentpropagation) and #37395 (an earlier fix isolating per-request server traces).Reproduction script (repro.sh)
Run it:
bash repro.sh