paperclipai/paperclip · error

OpenCode session creation omitted its id

Error message

OpenCode session creation omitted its id

What it means

When creating a fresh OpenCode session via POST /session, the driver extracts the id from the response with text(record(created).id) and throws this error if the resulting id is empty/undefined — the server responded but did not include the required session identifier.

Source

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

        const fetcher = this.#options.fetch ?? globalThis.fetch;
        let providerSessionId =
          snapshot?.providerSessionId ?? snapshot?.driverSessionId ?? null;
        if (providerSessionId !== null) {
          const existing = await api(
            fetcher,
            runtime,
            `/session/${encodeURIComponent(providerSessionId)}`,
          );
          if (!isRecord(existing) || text(existing.id) !== providerSessionId)
            throw new Error("OpenCode resumed a different session");
        } else {
          const created = await api(fetcher, runtime, "/session", {
            method: "POST",
            body: JSON.stringify({ title: `Paperclip ${input.runId}` }),
          });
          providerSessionId = text(record(created).id);
          if (!providerSessionId)
            throw new Error("OpenCode session creation omitted its id");
        }
        session = new OpenCodeHarnessSession({
          runtime,
          fetcher,
          runId: input.runId,
          normalizedSessionId: input.normalizedSessionId,
          providerSessionId,
          workingDirectory: cwd,
          runnerInstanceId:
            this.#options.runnerInstanceId ??
            `paperclip-opencode-${input.runId}`,
          model: this.#options.model,
          taskEnvelope:
            this.#options.taskEnvelope ??
            createCodexTaskEnvelope({
              objective: "Complete the supplied task.",
            }),
          systemInstructions:

View on GitHub (pinned to 01ad858492)

Solutions

  1. Call POST /session manually and inspect the response body — confirm it contains a non-empty id.
  2. Upgrade the OpenCode server to the API version the driver expects (contract drift on the session record shape).
  3. Check for proxies/middleware rewriting the /session response and bypass them.
  4. Log the full created payload; if it's an error object, surface the server's real error instead of the missing id.

Example fix

// before
const created = await api(fetcher, runtime, '/session', { method: 'POST', body: JSON.stringify({ title: `Paperclip ${input.runId}` }) });
// after (assert shape early)
const created = await api(fetcher, runtime, '/session', { method: 'POST', body: JSON.stringify({ title: `Paperclip ${input.runId}` }) });
if (!isRecord(created) || typeof created.id !== 'string' || !created.id)
  throw new Error(`OpenCode /session returned no id: ${JSON.stringify(created)}`);
Defensive patterns

Strategy: retry

Validate before calling

const probe = await fetch(`${baseUrl}/session`, { method: 'POST', body: JSON.stringify({ title: 'healthcheck' }) });
const probeBody = await probe.json();
if (typeof probeBody?.id !== 'string' || !probeBody.id) throw new Error(`OpenCode server /session shape invalid: ${JSON.stringify(probeBody)}`);

Type guard

const hasSessionId = (v: unknown): v is { id: string } => isRecord(v) && typeof v.id === 'string' && v.id.length > 0;

Try / catch

try { await openSession(input); } catch (e) { if ((e as Error).message === 'OpenCode session creation omitted its id') { await assertOpenCodeServerCompatible(); await openSession(input); } else throw e; }

Prevention

When it happens

Trigger: POST /session returns 2xx with a body lacking an id field, an error-shaped body, or a record whose id is not a string — e.g. incompatible OpenCode server version or a proxy intercepting the response.

Common situations: Version mismatch between driver and OpenCode server API, gateway returning HTML/error JSON without id, server bug omitting id, hitting the wrong endpoint (proxy rewriting /session).

Understand the failure class

Background: "invalid response format", "malformed payload", "missing data field": when an API returns 200 but the response shape is wrong — this error's family across 23 libraries.

Related errors


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