paperclipai/paperclip · error

OpenCode event stream returned HTTP ${response.status}

Error message

OpenCode event stream returned HTTP ${response.status}

What it means

Thrown when the driver opens the OpenCode server's SSE event stream and the HTTP response is not ok or has no body. The message embeds the HTTP status so the developer can see whether the endpoint rejected auth, was not found, or the server is unhealthy.

Source

Thrown at packages/paperclip-runner/src/drivers/opencode/opencode-server-driver.ts:1160

        },
      },
      { turnId, itemId: request.itemId },
    );
  }

  async #pumpEvents(): Promise<void> {
    let attempts = 0;
    while (!this.#closed && !this.#abort.signal.aborted) {
      try {
        const response = await this.#fetch(`${this.#runtime.baseUrl}/event`, {
          headers: {
            Authorization: this.#runtime.authHeader,
            Accept: "text/event-stream",
          },
          signal: this.#abort.signal,
        });
        if (!response.ok || !response.body)
          throw new Error(
            `OpenCode event stream returned HTTP ${response.status}`,
          );
        const outboundFrameId = this.#runtime.trace?.frame({
          direction: "client_to_provider",
          raw: "",
          transport: "http_sse",
          nativeMethod: "GET /event",
        });
        if (outboundFrameId) {
          this.#runtime.trace?.interpretation({
            frameId: outboundFrameId,
            stage: "typescript_opencode_http_transport",
            ruleId: "opencode.http.GET_event",
            disposition: "operator_only",
            reason: "Opened the OpenCode server-sent event stream",
          });
        }
        for await (const frame of parseSseFrames(response.body)) {

View on GitHub (pinned to 01ad858492)

Solutions

  1. Check the HTTP status in the message: 401/403 means fix the authHeader; 404 means the event endpoint path changed (check server version).
  2. Verify the OpenCode server process is alive and healthy at the configured base URL before opening the stream.
  3. Confirm any proxy in front of OpenCode supports streaming responses and is not stripping the SSE body.
  4. Retry session startup — the driver already retries up to 3 times, so persistent failure means a configuration issue.

Example fix

// before
const res = await fetch(`${baseUrl}/event`, { headers });

// after
const res = await fetch(`${baseUrl}/event`, { headers });
if (res.status === 401) {
  throw new Error("Event stream auth rejected — refresh authHeader from server health/startup");
}
Defensive patterns

Strategy: retry

Validate before calling

const health = await fetch(`${baseUrl}/health`);
if (!health.ok) throw new Error(`OpenCode server unhealthy: HTTP ${health.status}`);

Try / catch

try {
  await openStream();
} catch (e) {
  if (e instanceof Error && /event stream returned HTTP (401|403)/.test(e.message)) {
    authHeader = await refreshAuth(); // re-auth before retrying
  } else if (/event stream returned HTTP (502|503|504)/.test(e.message)) {
    await backoff(); // transient upstream — retry with backoff
  }
}

Prevention

When it happens

Trigger: The driver issues a GET for the event stream with Authorization/Accept: text/event-stream headers and receives a non-2xx status (e.g. 401, 404, 502), or a 200 without a readable body.

Common situations: Wrong or expired authHeader after the server restarted with new credentials; proxy/load balancer returning 502/503; OpenCode server version whose event endpoint path differs; server crashed mid-startup.

Understand the failure class

Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.

Related errors


AI-assisted analysis of paperclipai/paperclip@01ad858492 (2026-09-10). Data as JSON: /api/errors/25c6c4dcaa210ec7. Report an issue: GitHub.