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

  1. Inspect the error text in the stream event and the plugin/provider logs for the root cause
  2. Retry the request if the underlying error was transient (429/5xx from the provider)
  3. 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

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


AI-assisted analysis of router-for-me/CLIProxyAPI@78f0c4079e (2026-08-15). Data as JSON: /api/errors/e79ec63aee18e7a2. Report an issue: GitHub.