sigoden/aichat · error · anyhow::Error
Failed to read json stream
Error message
Failed to read json stream, {err} What it means
In src/client/stream.rs `json_stream` iterates an async byte stream and wraps any per-chunk transport failure with `Failed to read json stream, {err}`. It indicates the HTTP/byte stream carrying the JSON (e.g. a Gemini streaming completion) broke mid-read, before the JSON could be parsed.
Solutions
- Retry the request; streaming drops are often transient.
- Check network/proxy stability (timeouts on corporate proxies commonly kill SSE streams).
- Reduce response size or use non-streaming mode if the network drops long streams.
- Inspect the inner error `{err}` for the root transport cause (e.g. hyper `IncompleteMessage`).
Defensive patterns
Strategy: retry
Try / catch
// Rust
match json_stream(...).await {
Err(e) if e.to_string().contains("Failed to read json stream") => {
// log inner cause, backoff, and retry the request
retry_with_backoff(|| gemini_chat_completions_streaming(...)).await?;
}
other => other?,
} Prevention
- Use stable networks or wire connections for long streams.
- Configure proxy/client timeouts larger than expected stream duration.
- Prefer non-streaming mode on unreliable links.
- Log the inner error source for diagnosis.
When it happens
Trigger: `json_stream` receives `Err(e)` from `stream.next().await` while consuming a streaming response (e.g. `gemini_chat_completions_streaming`): connection reset, timeout, proxy drop, TLS termination mid-body.
Common situations: Long-running LLM streaming responses dropped by flaky networks or proxies; server-side aborts; VPN/mobile connection changes mid-stream.
Related errors
AI-assisted analysis of sigoden/aichat@82976d349a (2026-09-09).
Data as JSON: /api/errors/f56862efe35fda11.
Report an issue: GitHub.
Appendix: source
Thrown at src/client/stream.rs:154
}
es.close();
}
}
}
Ok(())
}
pub async fn json_stream<S, F, E>(mut stream: S, mut handle: F) -> Result<()>
where
S: Stream<Item = Result<bytes::Bytes, E>> + Unpin,
F: FnMut(&str) -> Result<()>,
E: std::error::Error,
{
let mut parser = JsonStreamParser::default();
let mut unparsed_bytes = vec![];
while let Some(chunk_bytes) = stream.next().await {
let chunk_bytes =
chunk_bytes.map_err(|err| anyhow!("Failed to read json stream, {err}"))?;
unparsed_bytes.extend(chunk_bytes);
match std::str::from_utf8(&unparsed_bytes) {
Ok(text) => {
parser.process(text, &mut handle)?;
unparsed_bytes.clear();
}
Err(_) => {
continue;
}
}
}
if !unparsed_bytes.is_empty() {
let text = std::str::from_utf8(&unparsed_bytes)?;
parser.process(text, &mut handle)?;
}
Ok(())
}View on GitHub (pinned to 82976d349a)