paperclipai/paperclip · error

OpenCode session is not ready for tool calls

Error message

OpenCode session is not ready for tool calls

What it means

The OpenCode server driver wires a dispatch callback that forwards tool calls to the active session. It throws this error if a tool call arrives while the internal session handle is still null, i.e. before the HTTP session fetch/create sequence has completed and a OpenCodeHarnessSession has been assigned.

Source

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

    const trace = await createProviderTraceFileSink({
      path: this.#options.environment?.PAPERCLIP_PROVIDER_TRACE_PATH,
      provider: "opencode",
      channel: "typescript_opencode_native",
      maxBytes: this.#options.environment?.PAPERCLIP_PROVIDER_TRACE_MAX_BYTES,
    });
    let lastError: unknown = null;
    for (let attempt = 1; attempt <= 3; attempt += 1) {
      let session: OpenCodeHarnessSession | null = null;
      let runtime: OpenCodeRuntime | null = null;
      try {
        runtime = await startRuntime({
          options: this.#options,
          root,
          cwd,
          trace,
          dispatch: (call) => {
            if (session === null)
              throw new Error("OpenCode session is not ready for tool calls");
            return session.dispatchTool(call);
          },
        });
        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}` }),

View on GitHub (pinned to 01ad858492)

Solutions

  1. Ensure no tool calls are dispatched until the driver's open/openSession promise resolves.
  2. Check that the resume endpoint (`GET /session/:id`) isn't hanging or failing silently, delaying session assignment.
  3. Upgrade the driver/harness so session assignment happens before attaching the tool dispatcher.
  4. Reproduce with trace logging to confirm whether the call arrives before session creation and fix the ordering.

Example fix

// before
const driver = new OpenCodeServerDriver(...);
driver.dispatchTool(call); // session not yet opened
// after
await driver.openSession(input);
driver.dispatchTool(call);
Defensive patterns

Strategy: try-catch

Validate before calling

// gate tool dispatch on session readiness
if (!driver.isSessionReady()) throw new Error('wait for openSession() before dispatching tool calls');

Type guard

const sessionReady = (d: { isSessionReady?(): boolean }): boolean => d.isSessionReady?.() ?? false;

Try / catch

try { return dispatchCall(call); } catch (e) { if ((e as Error).message === 'OpenCode session is not ready for tool calls') { await driver.openSession(input); return dispatchCall(call); } throw e; }

Prevention

When it happens

Trigger: A tool call is dispatched during #open before the async /session or /session/:id API call resolves, e.g. a re-entrant or early callback from the harness, or resume path throwing before session assignment.

Common situations: Race between harness initialization and first tool call, provider session lookup taking long while the agent already emits calls, bugs in mocked/fake fetchers that dispatch early.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


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