{"record":{"id":"e6394f108c280b79","repo":"paperclipai/paperclip","slug":"cloudflare-sandbox-bridge-request-timed-out-after","errorCode":null,"errorMessage":"Cloudflare sandbox bridge request timed out after ${requestTimeoutMs}ms.","messagePattern":"Cloudflare sandbox bridge request timed out after (.+?)ms\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/plugins/sandbox-providers/cloudflare/src/bridge-client.ts","lineNumber":136,"sourceCode":"    });\n    const body = await parseJson(response);\n    if (!response.ok) {\n      const errorBody = isRecord(body) ? body as BridgeErrorBody : {};\n      throw new CloudflareBridgeError({\n        status: response.status,\n        code: typeof errorBody.error === \"string\" ? errorBody.error : null,\n        message:\n          typeof errorBody.message === \"string\" && errorBody.message.trim().length > 0\n            ? errorBody.message\n            : `Cloudflare sandbox bridge request failed with HTTP ${response.status}.`,\n        details: errorBody.details,\n      });\n    }\n    return body as T;\n  } catch (error) {\n    if (error instanceof CloudflareBridgeError) throw error;\n    if ((error as { name?: string } | null)?.name === \"AbortError\") {\n      throw new Error(\n        `Cloudflare sandbox bridge request timed out after ${requestTimeoutMs}ms.`,\n      );\n    }\n    throw error;\n  } finally {\n    clearTimeout(timeout);\n  }\n}\n\nasync function requestResponse(\n  config: CloudflareDriverConfig,\n  path: string,\n  init: RequestInit,\n  extraHeaders: BridgeClientHeaders = {},\n): Promise<Response> {\n  const controller = new AbortController();\n  const requestTimeoutMs = resolveRequestTimeoutMs(config, path, init);\n  const timeout = setTimeout(() => controller.abort(), requestTimeoutMs);","sourceCodeStart":118,"sourceCodeEnd":154,"githubUrl":"https://github.com/paperclipai/paperclip/blob/67001ec6eb96ae601aa27bc91d9b2415d665334a/packages/plugins/sandbox-providers/cloudflare/src/bridge-client.ts#L118-L154","documentation":"Thrown by the Cloudflare bridge client's `requestJson` (bridge-client.ts:136-138) when the `AbortController` fires before the bridge responds. The request timeout is `resolveRequestTimeoutMs(config, path, init)`; for `/exec` it is the max of the configured `bridgeRequestTimeoutMs` and the body's requested `timeoutMs`, otherwise it is the configured default. The AbortError is converted into this plain Error.","triggerScenarios":"Any JSON bridge call takes longer than the resolved request timeout: a long-running non-streaming `/exec` command, a slow `/leases/acquire` cold start, or network latency/edge stalls between the driver and the bridge Worker.","commonSituations":"Running a synchronous command via `/exec` without `streamOutput` that legitimately runs long; bridge or Cloudflare edge congestion; or `bridgeRequestTimeoutMs` configured too low for the workload.","solutions":["Raise `bridgeRequestTimeoutMs` in the driver config, or pass a larger `timeoutMs` in the exec body.","For long-running commands, use the streaming exec path (supply `onOutput`) so the response is an SSE stream not bounded by the JSON request timeout.","Retry transient network-induced timeouts."],"exampleFix":"// before\nawait client.execute({ providerLeaseId, command: \"npm run build\", timeoutMs: 5000 });\n// after\nawait client.execute({ providerLeaseId, command: \"npm run build\", timeoutMs: 60000 }, headers, { onOutput: console.log });","handlingStrategy":"retry","validationCode":"// Raise the configured request timeout for long commands.\nconfig.bridgeRequestTimeoutMs = Math.max(config.bridgeRequestTimeoutMs ?? 30000, 120000);","typeGuard":"function isBridgeTimeout(e: unknown): boolean {\n  return e instanceof Error && /bridge request timed out/.test(e.message);\n}","tryCatchPattern":"async function execWithRetry(client, body, headers) {\n  for (let i = 0; i < 2; i++) {\n    try {\n      return await client.execute({ ...body, timeoutMs: 60000 }, headers);\n    } catch (err) {\n      if (isBridgeTimeout(err) && i === 0) continue;\n      throw err;\n    }\n  }\n}","preventionTips":["Use the streaming exec path (onOutput) for long-running commands.","Size bridgeRequestTimeoutMs to the slowest legitimate command.","Retry once on transient network timeouts."],"tags":["cloudflare","sandbox","timeout","bridge","network"],"backgroundTag":null,"analyzedSha":"67001ec6eb96ae601aa27bc91d9b2415d665334a","analyzedAt":"2026-08-12T12:05:45.408Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}