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
callTool does not retry on transient network errors (socket closed during concurrent requests) #114
When multiple callTool() requests run concurrently (e.g. generating variants with Pro model), the Stitch server occasionally closes the underlying socket. The SDK surfaces this as an unrecoverable TypeError: fetch failed to the caller, even though the operation would succeed on a simple retry with a fresh connection.
Steps to reproduce
constclient=newStitchToolClient({apiKey: "..."});constproject=awaitclient.callTool("create_project",{title: "test"});constprojectId=project.name.replace("projects/","");constscreen=awaitclient.callTool("generate_screen_from_text",{
projectId,prompt: "a dashboard",modelId: "GEMINI_3_PRO",});constscreenId=screen.outputComponents[0].design.screens[0].id;// Fire 3 concurrent variant requests — one or more will failawaitPromise.allSettled([client.callTool("generate_variants",{
projectId,selectedScreenIds: [screenId],prompt: "dark theme",variantOptions: {variantCount: 2,creativeRange: "EXPLORE"},modelId: "GEMINI_3_PRO",}),client.callTool("generate_variants",{/* ... */}),client.callTool("generate_variants",{/* ... */}),]);
Actual behavior
Stitch Transport Error: TypeError: fetch failed
[cause]: SocketError: other side closed
One or more requests fail with no retry attempt. The transport's onerror sets isConnected = false, but the in-flight request is already lost.
Expected behavior
callTool should detect transient network errors (e.g. fetch failed, ECONNRESET, socket), reconnect, and retry the request once before throwing.
Environment
@google/stitch-sdk 0.0.3
Node.js 22
macOS
Reproducible with GEMINI_3_PRO model under concurrent variant generation
Server-side generation continues after client disconnect — The client received TypeError: fetch failed (socket closed), but the Stitch backend completed generation. Screens are visible in the web UI.
list_screens returns 0 for these projects — Even for screens that were successfully returned to the client, list_screens shows nothing. This means the tool description's advice ("try to get the screen with get_screen method later") may not work as a recovery path.
Quota is consumed on disconnect — Failed requests still result in generated screens on the server. This reinforces that write operations should NOT be retried (which our PR implements).
Opened #363 — callTool reconnects and retries once on transient network errors (fetch failed, socket closed, ECONNRESET).
Write operations are not retried; only the transport reconnect path runs before a single retry, matching the concern in the thread about server-side completion after disconnect.
Tests added in packages/sdk/test/unit/client.test.ts.
Activity
fix: retry callTool once on transient network errors
icebear0828 commentedon Mar 18, 2026
Additional finding:
list_screensdoes not return screens generated viagenerate_screen_from_textDuring stress testing (10 and 20 concurrent
generate_screen_from_textcalls), we found:Test results
list_screensAPIProject links
Key observations
Server-side generation continues after client disconnect — The client received
TypeError: fetch failed(socket closed), but the Stitch backend completed generation. Screens are visible in the web UI.list_screensreturns 0 for these projects — Even for screens that were successfully returned to the client,list_screensshows nothing. This means the tool description's advice ("try to get the screen withget_screenmethod later") may not work as a recovery path.Quota is consumed on disconnect — Failed requests still result in generated screens on the server. This reinforces that write operations should NOT be retried (which our PR implements).
Impact on PR #115
This confirms the retry design is correct:
drmikecrypto commentedon Jun 27, 2026
Opened #363 —
callToolreconnects and retries once on transient network errors (fetch failed, socket closed, ECONNRESET).Write operations are not retried; only the transport reconnect path runs before a single retry, matching the concern in the thread about server-side completion after disconnect.
Tests added in
packages/sdk/test/unit/client.test.ts.