router-for-me/CLIProxyAPI · error
%s
Error message
%s
What it means
The stream bridge in internal/pluginhost/stream_bridge.go received a close request whose errorMessage was non-empty and converts it into a terminal stream chunk (Err: fmt.Errorf("%s", errorMessage)) that is flushed to the SSE consumer before the stream ends. It is the mechanism that surfaces a plugin-side streaming failure (mid-generation error, aborted request) as an error event in the OpenAI/Gemini/Claude-compatible stream.
Source
Thrown at internal/pluginhost/stream_bridge.go:101
var emitC <-chan streamBridgeEmit
if len(queue) < streamBridgeBufferSize {
emitC = s.emits
}
var outputC chan pluginapi.ExecutorStreamChunk
var next pluginapi.ExecutorStreamChunk
if len(queue) > 0 {
outputC = s.chunks
next = queue[0]
}
select {
case <-s.abort:
return
case request := <-s.closes:
s.markClosed()
close(request.accepted)
if request.errorMessage != "" {
queue = append(queue, pluginapi.ExecutorStreamChunk{Err: fmt.Errorf("%s", request.errorMessage)})
}
for len(queue) > 0 {
select {
case <-s.abort:
return
case s.chunks <- queue[0]:
queue = queue[1:]
}
}
return
case request := <-emitC:
if err := request.ctx.Err(); err != nil {
request.done <- err
continue
}
queue = append(queue, request.chunk)
request.done <- nil
case outputC <- next:View on GitHub (pinned to 78f0c4079e)
Solutions
- Inspect the error text in the stream event and the plugin/provider logs for the root cause
- Retry the request if the underlying error was transient (429/5xx from the provider)
- If you own the plugin, ensure stream errors carry a descriptive message so this chunk is diagnosable
Defensive patterns
Strategy: try-catch
Try / catch
for chunk := range stream {
if chunk.Err != nil {
if isTransient(chunk.Err) { // 429/5xx text from provider
return retryWithBackoff(ctx, req)
}
return chunk.Err // terminal stream error from plugin close
}
emit(chunk)
} Prevention
- Treat any chunk carrying Err as terminal for that stream; do not continue consuming after it
- Retry only transient provider errors; propagate the message text to the client's error event
When it happens
Trigger: A streaming executor call to a plugin fails partway: the host closes the bridge with an errorMessage, and the queued chunk carrying that error is delivered on the chunks channel before return.
Common situations: Upstream provider error during generation (rate limit, content filter, disconnect); plugin panic during streaming; client disconnect racing the close path (queued chunks drained until abort).
Related errors
- plugin executor %s stream panic: %v
- model stream bridge is unavailable
- %s
- count must be a positive integer
- invalid_realtime_client_secret
AI-assisted analysis of router-for-me/CLIProxyAPI@78f0c4079e (2026-08-15).
Data as JSON: /api/errors/e79ec63aee18e7a2.
Report an issue: GitHub.