plandex-ai/plandex · error
stream timeout due to inactivity: The AI model (%s/%s) is no
Error message
stream timeout due to inactivity: The AI model (%s/%s) is not responding
What it means
listenStream in tell_stream_main.go guards against a stalled LLM stream with a first-token/inactivity timer (sized by totalRequestTokens). If no chunk arrives from the model within the timeout and the stream hasn't finished, it raises 'stream timeout due to inactivity: The AI model (provider/model) is not responding' via state.onError with storeDesc=true and canRetry set only when zero output was received. This is a client-side watchdog, not a model error response.
Source
Thrown at app/server/model/plan/tell_stream_main.go:103
mainLoop:
for {
select {
case <-active.Ctx.Done():
// The main modelContext was canceled (not the timer)
log.Println("\nTell: stream canceled")
state.execHookOnStop(false)
return
case <-timer.C:
// Timer triggered because no new chunk was received in time
log.Println("\nTell: stream timeout due to inactivity")
if streamFinished {
log.Println("Tell stream finished—timed out waiting for usage chunk")
state.execHookOnStop(false)
return
} else {
res := state.onError(onErrorParams{
streamErr: fmt.Errorf("stream timeout due to inactivity: The AI model (%s/%s) is not responding", modelProvider, modelName),
storeDesc: true,
canRetry: active.CurrentReplyContent == "", // if there was no output yet, we can retry
})
if res.shouldReturn {
return
}
if res.shouldContinueMainLoop {
continue mainLoop
}
}
case err := <-streamErrCh:
log.Printf("listenStream - received from streamErrCh: %v\n", err)
if err.Error() == "context canceled" {
log.Println("Tell: stream context canceled")
state.execHookOnStop(false)View on GitHub (pinned to e2d772072e)
Solutions
- Retry the request (automatically allowed when no output was produced yet, canRetry=true)
- Check the named provider/model status — it is embedded in the message
- For local models, increase the first-token timeout or warm up the model before requests
- Verify network path/proxy isn't silently dropping idle connections
Example fix
// before
res := state.onError(onErrorParams{
streamErr: fmt.Errorf("stream timeout due to inactivity: The AI model (%s/%s) is not responding", modelProvider, modelName),
storeDesc: true,
canRetry: active.CurrentReplyContent == "",
})
// after
// warm up / health-check the model before long requests, and make timeout configurable
timeout := firstTokenTimeout(state.totalRequestTokens, baseModelConfig.LocalOnly)
log.Printf("listenStream: inactivity timeout %s for %s/%s", timeout, modelProvider, modelName)
res := state.onError(onErrorParams{
streamErr: fmt.Errorf("stream timeout due to inactivity: The AI model (%s/%s) is not responding", modelProvider, modelName),
storeDesc: true,
canRetry: active.CurrentReplyContent == "",
}) Defensive patterns
Strategy: retry
Validate before calling
if baseModelConfig.LocalOnly && !isLocalModelReady(provider, model) {
return fmt.Errorf("local model %s/%s not ready; skipping request", provider, model)
} Try / catch
case <-timer.C:
res := state.onError(onErrorParams{
streamErr: fmt.Errorf("stream timeout due to inactivity: The AI model (%s/%s) is not responding", modelProvider, modelName),
storeDesc: true,
canRetry: active.CurrentReplyContent == "",
})
if res.shouldReturn {
return
} Prevention
- Enable retries only when no partial output exists to avoid duplicated replies
- Size the inactivity timeout by request size and model type (local vs hosted)
- Health-check/warm up local models before sending large requests
- Monitor provider stall rates and set upstream keep-alives to avoid silent connection drops
When it happens
Trigger: stream.Recv() blocks beyond firstTokenTimeout: provider hang, network black hole (no TCP reset), overloaded model backend, or a locally-hosted model that is still loading.
Common situations: Self-hosted/local model cold-start exceeding the timeout; provider outage or rate-limit stall; network middlebox silently dropping the connection; very large request causing long queue time.
Understand the failure class
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- stream timed out due to inactivity. The model is not respond
- connection to plan stream timed out due to missing heartbeat
- context canceled while waiting to retry: %w
- error creating chat completion stream: %w
- model stream ended unexpectedly: %w
AI-assisted analysis of plandex-ai/plandex@e2d772072e (2026-09-05).
Data as JSON: /api/errors/34a984d57e31d420.
Report an issue: GitHub.