fix: prevent TransferEncodingError in Gemini SSE stream#2322
fix: prevent TransferEncodingError in Gemini SSE stream#2322Stranmor wants to merge 1 commit intolbjlaq:mainfrom
Conversation
When SSE streams encounter errors (timeout, upstream connection drop), the Gemini handler uses yield Err(...) which causes hyper to abort HTTP/1.1 chunked transfer encoding without sending the final 0\r\n\r\n terminator. HTTP clients that validate chunk boundaries (aiohttp, httpx) then throw TransferEncodingError. Fix: convert stream errors to Ok(Bytes) SSE content (matching the pattern already used by the OpenAI handler), so the stream terminates cleanly and hyper sends the proper chunked encoding terminator. Affected path: Gemini streaming handler Already fixed: OpenAI streaming handler (errors wrapped as Ok) Partially mitigated: Claude handler (.map wrapper converts Err→Ok)
2759a95 to
bca2492
Compare
|
Closing as duplicate of #2321 which covers both Gemini and Claude SSE streams. |
|
Reopening — this PR uses serde_json::json!() for proper JSON escaping, which is safer than the manual format!() + replace() approach in #2321. |
|
When trying to change accounts in the accounts section, I get a "storage json not found" error. |
|
Hello, thank you for contacting us. Where exactly should I do this? Should we communicate via email or GitHub? Also, I actively use the application daily and, if you don't mind, I can offer suggestions for fixes and updates.
Android için Outlook<https://aka.ms/AAb9ysg> edinin
…________________________________
From: Ivan Plankin ***@***.***>
Sent: Wednesday, March 25, 2026 8:20:46 AM
To: lbjlaq/Antigravity-Manager ***@***.***>
Cc: adam2626 ***@***.***>; Mention ***@***.***>
Subject: Re: [lbjlaq/Antigravity-Manager] fix: prevent TransferEncodingError in Gemini SSE stream (PR #2322)
[https://avatars.githubusercontent.com/u/49376798?s=20&v=4]Stranmor left a comment (lbjlaq/Antigravity-Manager#2322)<#2322 (comment)>
Hi @adam2626<https://github.com/adam2626>! Thanks for reporting this. The "storage json not found" error is unrelated to this PR — this fix only addresses SSE stream TransferEncodingError issues. This looks like a separate bug in the account storage logic. Could you open a new issue for it so we can track and fix it properly?
—
Reply to this email directly, view it on GitHub<#2322?email_source=notifications&email_token=AKIVKGYYZ45CY75SPS3LDV34SNUC3A5CNFSNUABFM5UWIORPF5TWS5BNNB2WEL2JONZXKZKDN5WW2ZLOOQXTIMJSGM3TKMJTGEYKM4TFMFZW63VHNVSW45DJN5XKKZLWMVXHJLDGN5XXIZLSL5RWY2LDNM#issuecomment-4123751310>, or unsubscribe<https://github.com/notifications/unsubscribe-auth/AKIVKGZNM7KNCK3MYITFILT4SNUC3AVCNFSM6AAAAACWRHNHSWVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHM2DCMRTG42TCMZRGA>.
You are receiving this because you were mentioned.Message ID: ***@***.***>
|
|
Hey @adam2626! I have opened a dedicated issue to track and fix the storage JSON bug we discussed: #2371 And yes, suggestions for fixes and improvements are always welcome! Feel free to open issues with anything you notice or would like to improve. GitHub is the preferred channel for this, as it keeps everything public and searchable. |
|
Hi @adam2626, I owe you an apology — my previous analysis was wrong. You were absolutely right, this PR IS the indirect cause of the "storage json not found" error. Here's what actually happens:
Thank you for catching this! The fix is to wrap the error message inside a structurally valid OpenAI SSE chunk so the IDE doesn't crash. I'll work on a patch for this. Good catch! |
|
Thank you so much for your attention. I have one more question. Please don't misunderstand, there are many rumors about information theft or leakage related to API keys. I'm certainly not saying you did it. After your behavior, I have no doubt that you did it, but that wouldn't happen, would it?
Android için Outlook<https://aka.ms/AAb9ysg> edinin
…________________________________
From: Ivan Plankin ***@***.***>
Sent: Wednesday, March 25, 2026 9:40:19 AM
To: lbjlaq/Antigravity-Manager ***@***.***>
Cc: adam2626 ***@***.***>; Mention ***@***.***>
Subject: Re: [lbjlaq/Antigravity-Manager] fix: prevent TransferEncodingError in Gemini SSE stream (PR #2322)
[https://avatars.githubusercontent.com/u/49376798?s=20&v=4]Stranmor left a comment (lbjlaq/Antigravity-Manager#2322)<#2322 (comment)>
Hi @adam2626<https://github.com/adam2626>, I owe you an apology — my previous analysis was wrong. You were absolutely right, this PR IS the indirect cause of the "storage json not found" error.
Here's what actually happens:
1. This PR changes the error format to a clean JSON object instead of a broken stream.
2. The IDE parser expects a standard OpenAI chunk (choices[0].delta). When it receives our custom error JSON, it throws a JavaScript TypeError and crashes/freezes the chat UI.
3. Because the UI is frozen, you close the IDE.
4. When you then click 'Switch Account' in Antigravity-Manager, it tries to find storage.json by scanning the running IDE process. Since the IDE is now closed, the process discovery fails, resulting in the "storage json not found" error.
Thank you for catching this! The fix is to wrap the error message inside a structurally valid OpenAI SSE chunk so the IDE doesn't crash. I'll work on a patch for this. Good catch!
—
Reply to this email directly, view it on GitHub<#2322?email_source=notifications&email_token=AKIVKG2IQTYVHPV3E7QXLK34SN5NHA5CNFSNUABFM5UWIORPF5TWS5BNNB2WEL2JONZXKZKDN5WW2ZLOOQXTIMJSGQYTMNZYGAZKM4TFMFZW63VHNVSW45DJN5XKKZLWMVXHJLDGN5XXIZLSL5RWY2LDNM#issuecomment-4124167802>, or unsubscribe<https://github.com/notifications/unsubscribe-auth/AKIVKG5IOFETST5V55326TD4SN5NHAVCNFSM6AAAAACWRHNHSWVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHM2DCMRUGE3DOOBQGI>.
You are receiving this because you were mentioned.Message ID: ***@***.***>
|
|
I really liked your project; I'm using AI tools here for free that I would normally pay a lot of money for. I'm not saying this specifically for you, but there's a saying: "Free cheese is only found in a mousetrap." Of course, you can charge for this work, that's your right, but you don't seem to be expecting anything in return. Look, the examples I gave are definitely not for you; I'm just a beginner with AI and GitHub resources. I'm trying to do projects or different things with AI, and I really liked your project. I want to give you feedback as much as I can.
Android için Outlook<https://aka.ms/AAb9ysg> edinin
…________________________________
From: Ivan Plankin ***@***.***>
Sent: Wednesday, March 25, 2026 9:40:19 AM
To: lbjlaq/Antigravity-Manager ***@***.***>
Cc: adam2626 ***@***.***>; Mention ***@***.***>
Subject: Re: [lbjlaq/Antigravity-Manager] fix: prevent TransferEncodingError in Gemini SSE stream (PR #2322)
[https://avatars.githubusercontent.com/u/49376798?s=20&v=4]Stranmor left a comment (lbjlaq/Antigravity-Manager#2322)<#2322 (comment)>
Hi @adam2626<https://github.com/adam2626>, I owe you an apology — my previous analysis was wrong. You were absolutely right, this PR IS the indirect cause of the "storage json not found" error.
Here's what actually happens:
1. This PR changes the error format to a clean JSON object instead of a broken stream.
2. The IDE parser expects a standard OpenAI chunk (choices[0].delta). When it receives our custom error JSON, it throws a JavaScript TypeError and crashes/freezes the chat UI.
3. Because the UI is frozen, you close the IDE.
4. When you then click 'Switch Account' in Antigravity-Manager, it tries to find storage.json by scanning the running IDE process. Since the IDE is now closed, the process discovery fails, resulting in the "storage json not found" error.
Thank you for catching this! The fix is to wrap the error message inside a structurally valid OpenAI SSE chunk so the IDE doesn't crash. I'll work on a patch for this. Good catch!
—
Reply to this email directly, view it on GitHub<#2322?email_source=notifications&email_token=AKIVKG2IQTYVHPV3E7QXLK34SN5NHA5CNFSNUABFM5UWIORPF5TWS5BNNB2WEL2JONZXKZKDN5WW2ZLOOQXTIMJSGQYTMNZYGAZKM4TFMFZW63VHNVSW45DJN5XKKZLWMVXHJLDGN5XXIZLSL5RWY2LDNM#issuecomment-4124167802>, or unsubscribe<https://github.com/notifications/unsubscribe-auth/AKIVKG5IOFETST5V55326TD4SN5NHAVCNFSM6AAAAACWRHNHSWVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHM2DCMRUGE3DOOBQGI>.
You are receiving this because you were mentioned.Message ID: ***@***.***>
|
|
Hey @adam2626, great question — totally fair concern. Here's how it works: Your actual AI provider API keys (Gemini, Claude, OpenAI, etc.) are never sent to the Antigravity server. The server doesn't want them, doesn't store them, and has no use for them. Instead, the local proxy authenticates with the Antigravity API using its own Antigravity Proxy Token (the When the proxy forwards your requests to AI providers, it uses the server's own internal keys — not yours. If you accidentally put your own provider API key in the IDE config, the proxy will actually strip it out before forwarding the request. The whole point of this architecture is that you don't need your own API keys for any AI provider. Access is managed through a quota system tied to your Antigravity account instead. So in short: your provider keys stay local (and aren't even needed), and the proxy token is the only credential that talks to the Antigravity server. Hope that clears things up! Let me know if you have any other questions. |
Problem
When upstream returns an error during Gemini SSE streaming, the handler yields
Err(String)intoBody::from_stream(). Axum/hyper interprets this as a transport-level failure and aborts the HTTP response with aTransferEncodingerror instead of delivering the error as a valid SSEdata:frame.Impact: HTTP clients (aiohttp, httpx, curl) see a broken chunked transfer instead of a parseable error event. This is the root cause of
TransferEncodingError/ClientPayloadErrorreports.Fix
Convert
yield Err(...)toyield Ok(Bytes::from(...))with a properly formatted SSE error event (data: {"error": ...}\n\n). This ensures error information reaches the client as valid SSE data rather than corrupting the HTTP transport layer.Files changed:
src-tauri/src/proxy/handlers/gemini.rs— primary fix (stream error yield)src-tauri/src/proxy/mappers/claude/mod.rs— defense-in-depth (same pattern)Verification
Ok(Bytes)pattern — this PR aligns Gemini and Claude mappers to the same contract