anthropics / anthropics/claude-agent-sdk-typescript
Issue: Streaming Text Deltas Pause for 3+ Minutes (No Events, No Pings)
- Lingua principale
- Shell
- Stelle
- 1.8k
- Fork
- 226
- Metriche di merge delle PR
- Nessuna PR unita negli ultimi 30g
Descrizione
### Description
When using the Claude API with streaming enabled, text delta events occasionally stop arriving for extended periods (3+ minutes), causing the UI to freeze while waiting for the next token. The API eventually resumes sending deltas and completes the response, but the user experience is severely degraded during these pauses.
**This occurs during regular text streaming, NOT during tool use** (which the documentation indicates may have delays).
### Environment
- **SDK**: Claude Agent SDK (via Claude Code SDK wrapper)
- **Model**: `claude-sonnet-4-5-20250929`
- **Streaming**: Enabled (processing `stream_event` messages with `content_block_delta`)
- **Content Type**: Text generation (first content block was `type: "text"`, not `tool_use`)
- **Date Observed**: October 24, 2025
### Documentation Reference
According to [Streaming Documentation](https://docs.claude.com/en/docs/build-with-claude/streaming):
> "Our current models only support emitting one complete key and value property from `input` at a time. As such, **when using tools**, there may be delays between streaming events while the model is working."
The documentation also states:
> "There may be `ping` events dispersed throughout the response as well."
**Key Points:**
- ✅ Documentation mentions delays for **tool use** (input JSON accumulation)
- ✅ Documentation promises `ping` events "dispersed throughout the response"
- ✅ Documentation mentions `overloaded_error` for high usage periods
- ❌ Documentation does NOT mention multi-minute pauses during text streaming
- ❌ Documentation does NOT explain gaps in `text_delta` events without `ping` events
### Our Implementation
We follow the documented async generator pattern for streaming:
Message Sending Code
```typescript
// Configure SDK options
const options = {
model: 'claude-sonnet-4-5-20250929',
maxTurns: 20,
includePartialMessages: true, // Enable real-time stream events
abortController: new AbortController(),
};
// Send message using streaming async generator pattern
const messageGenerator = createMessageGenerator(userMessage);
const claudeQuery = query({ prompt: messageGenerator, options });
// Iterate over streaming response
for await (const msg of claudeQuery) {
if (!msg) continue;
// Handle different message types
if (msg.type === 'stream_event') {
handleStreamEvent(msg.event);
}
}
```
Stream Event Handling Code
```typescript
// Process stream events
function handleStreamEvent(event: StreamEvent) {
// Log event type for debugging
console.log('Stream event:', {
type: event.type,
contentBlockType: event.type === 'content_block_start'
? event.content_block.type
: event.type === 'content_block_delta'
? event.delta.type
: 'N/A'
});
// Handle content block start
if (event.type === 'content_block_start') {
const block = event.content_block;
if (block.type === 'text') {
// Start accumulating text content
currentTextContent = block.text || '';
updateUI({
content: currentTextContent,
isComplete: false,
isStart: true
});
}
}
// Handle incremental updates
else if (event.type === 'content_block_delta') {
const delta = event.delta;
if (delta.type === 'text_delta') {
// Append new text to accumulated content
currentTextContent += delta.text;
// Update UI with new content (happens in 1-3ms)
updateUI({
content: currentTextContent,
isComplete: false,
isDelta: true
});
}
}
// Handle content block completion
else if (event.type === 'content_block_stop') {
updateUI({
content: currentTextContent,
isComplete: true
});
}
}
```
**Our implementation:**
- ✅ Uses documented async generator pattern
- ✅ Handles all stream event types per documentation
- ✅ Accumulates content incrementally as deltas arrive
- ✅ Updates UI within 1-3ms of receiving each delta
- ✅ Application confirmed running during gap (heartbeat logs)
- ✅ Network connectivity confirmed during gap (no errors)
### Reproduction
This issue appears to be intermittent and API-side. It occurred during a request for a long-form creative response (poem generation).
**Request:**
```
User: "create a long poem about a software engineer who loves to code..."
```
**Content Block Type:** `text` (index 0) - **NOT tool_use**
### Observed Behavior
**Timeline of stream events:**
1. **18:21:54.141**: `content_block_start` (type: `text`, index: 0)
2. **18:21:54.142-155**: Initial rapid `text_delta` events (13 updates in 13ms) ✅
3. **18:21:54.155 - 18:24:59.868**: **No events of ANY type for 185 seconds (3 min 5 sec)** ⚠️
- ❌ No `text_delta` events
- ❌ No `ping` events (documented as "dispersed throughout")
- ❌ No error events
- ❌ No keep-alive signals of any kind
4. **18:24:59.868 - 18:25:00.397**: Rapid burst of `text_delta` events (remaining ~28KB of content) ✅
5. **18:25:00.397**: `content_block_stop` and `message_stop` events (completion)
**Event log from our application:**
```typescript
[18:21:54.141] content_block_start { type: 'text', index: 0 }
[18:21:54.142] content_block_delta { type: 'text_delta', text: 'T' }
[18:21:54.143] content_block_delta { type: 'text_delta', text: 'he Ballad' }
[18:21:54.154] content_block_delta { type: 'text_delta', text: ' of the Code' }
[18:21:54.155] content_block_delta { type: 'text_delta', text: ' Mage...' }
// ⚠️ No events of ANY type for 185 seconds
// - No text_delta events
// - No ping events
// - No error events
// - Application still running (confirmed via heartbeat logs)
// - Network connection active (confirmed via system monitoring)
[18:24:59.868] content_block_delta { type: 'text_delta', text: ' flows...' }
[18:24:59.882] content_block_delta { type: 'text_delta', text: ' in streams' }
// ... rapid deltas resume for remaining ~28KB of content
[18:25:00.397] content_block_stop { index: 0 }
[18:25:00.397] message_stop
```
### Expected Behavior (Based on Documentation)
According to the streaming documentation:
1. **Consistent text streaming**: Text deltas should arrive continuously during text generation (delays only documented for tool use)
2. **Ping events**: Keep-alive `ping` events should be "dispersed throughout the response"
3. **Tool-only delays**: Delays are documented only for tool use, not text streaming
4. **Error events**: If there are issues (like `overloaded_error`), error events should be emitted
**None of these expectations were met during the 185-second gap.**
### Comparison: Documented vs. Observed
| Documented Behavior | Observed Behavior | Match? |
|---------------------|-------------------|---------|
| Delays only during tool use | Delay during text streaming (no tools) | ❌ No |
| `ping` events dispersed throughout | Zero `ping` events in 185s gap | ❌ No |
| Error events for issues | Silent gap with no events | ❌ No |
| Continuous text deltas | 185s gap between deltas | ❌ No |
### Impact
- **User Experience**: Users see the first few words, then nothing changes for 3+ minutes, appearing frozen
- **No feedback mechanism**: Without `ping` events or error events, impossible to distinguish between:
- Network failure
- API delay/throttling
- Application bug
- Model processing
- **Timeout implementation unclear**: No guidance on appropriate timeout values
- **Perceived Reliability**: Long silent pauses damage user trust in the API
- **Against Documentation**: Behavior contradicts documented streaming patterns
### Additional Context
- **Response size**: Final response was ~29KB of text (complete poem)
- **Network status**: No connection issues detected; application continued running with periodic heartbeat logs every 8 seconds
- **Content type**: Plain text generation (poem), **NOT tool use**
- **Initial performance**: First 13 deltas arrived in 13ms, showing no initial latency
- **Intermittent**: Similar requests on subsequent attempts worked correctly with consistent streaming
- **No errors**: No `overloaded_error` or other error events received during or after the gap
- **Our processing time**: When deltas arrive, we process them in 1-3ms (not a bottleneck)
### Questions for Maintainers
1. **Is this expected behavior?** The documentation only mentions delays for tool use, not text streaming
2. **Why no `ping` events?** Documentation explicitly says these should be dispersed throughout—we received none during the 185s gap
3. **Should errors/delays emit events?** Silent failures make it impossible to provide appropriate user feedback
4. **Extended thinking related?** Could this be related to the model's thinking/reasoning process? (But no `thinking_delta` events were emitted)
5. **Rate limiting?** Is there undocumented rate limiting or throttling that pauses streaming without notification?
6. **What timeout should we implement?** Without guidance on maximum expected delays, we can't distinguish normal delays from failures
### Suggested Solutions
1. **Emit `ping` events as documented**: Ensure keep-alive `ping` events are sent during processing delays
2. **Progress/status events**: Add new event types to indicate processing state:
```json
{"type": "processing_status", "status": "generating", "elapsed_ms": 30000}
```
3. **Error/throttle events**: If delays are due to overload/throttling, emit informative events:
```json
{"type": "stream_event", "event": {"type": "delay_notice", "reason": "high_load", "expected_delay_ms": 60000}}
```
4. **Thinking blocks**: If model is reasoning without outputting, emit `thinking_delta` events to show progress
5. **Update documentation**: If 3+ minute pauses are possible:
- Document maximum expected delays between events
- Provide guidance for timeout handling
- Clarify when delays can occur (not just tool use)
6. **Timeout guidance**: Specify recommended timeout values for different scenarios
---
**Impact**: This behavior contradicts the streaming documentation (no `ping` events, delays outside of tool use) and creates a poor user experience in production applications where users cannot distinguish between network failures and API delays.
Would appreciate clarification on:
- Whether this is expected behavior or a bug
- Why documented `ping` events were not sent
- What timeout values are appropriate for stream event intervals
- How to handle these silent gaps in production applications
Happy to provide additional telemetry, logs, or collaborate on reproducing this issue if helpful for debugging.
Guida per i contributori
Nessuna guida per i contributori indicizzata per questo repository
Valutazione
Questa issue non è ancora stata valutata.