router-for-me/CLIProxyAPI · error

ExecuteModelStream requires Stream=true

Error message

ExecuteModelStream requires Stream=true

What it means

Programmer error in the plugin/host model API: ExecuteModelStream() only performs streaming internal model requests, so calling it with ModelExecutionRequest{Stream: false} (the zero value) is rejected with a mode error. The non-streaming counterpart is ExecuteModel().

Source

Thrown at sdk/api/handlers/model_execution.go:124

		SkipRouterPluginID:      req.SkipRouterPluginID,
	})
	if errMsg != nil {
		return ModelExecutionResponse{}, errMsg
	}
	return ModelExecutionResponse{
		StatusCode: http.StatusOK,
		Headers:    cloneHeader(headers),
		Body:       cloneBytes(body),
	}, nil
}

// ExecuteModelStream executes an internal streaming model request.
// Host model callbacks are non-recursive for their caller: when
// skip plugin IDs are set, that plugin's interceptors and router are skipped
// for the nested model execution while other plugins may still run.
func (h *BaseAPIHandler) ExecuteModelStream(ctx context.Context, req ModelExecutionRequest) (ModelExecutionStream, *interfaces.ErrorMessage) {
	if !req.Stream {
		return ModelExecutionStream{}, modelExecutionModeError("ExecuteModelStream requires Stream=true")
	}
	dataChan, headers, errChan := h.executeStreamWithAuthManagerFormats(ctx, req.EntryProtocol, req.ExitProtocol, req.Model, cloneBytes(req.Body), req.Alt, false, modelExecutionOptions{
		Headers:                 req.Headers,
		Query:                   req.Query,
		InternalSource:          true,
		SkipInterceptorPluginID: req.SkipInterceptorPluginID,
		SkipRouterPluginID:      req.SkipRouterPluginID,
	})
	chunks, errMsg := prepareModelExecutionStream(ctx, dataChan, errChan)
	if errMsg != nil {
		return ModelExecutionStream{}, errMsg
	}
	return ModelExecutionStream{
		StatusCode: http.StatusOK,
		Headers:    cloneHeader(headers),
		Chunks:     chunks,
	}, nil
}

View on GitHub (pinned to 78f0c4079e)

Solutions

  1. Set Stream: true in the request passed to ExecuteModelStream
  2. If you want a single buffered response, call ExecuteModel instead

Example fix

// before
stream, errMsg := h.ExecuteModelStream(ctx, ModelExecutionRequest{Model: name, Body: body})
// after
stream, errMsg := h.ExecuteModelStream(ctx, ModelExecutionRequest{Model: name, Body: body, Stream: true})
Defensive patterns

Strategy: validation

Validate before calling

if !req.Stream {
    return nil, fmt.Errorf("use ExecuteModel for buffered responses; got Stream=false on ExecuteModelStream")
}
stream, errMsg := h.ExecuteModelStream(ctx, req)

Type guard

func isStreamingExecution(req ModelExecutionRequest) bool {
    return req.Stream
}

Try / catch

stream, errMsg := h.ExecuteModelStream(ctx, req)
if errMsg != nil && strings.Contains(errMsg.Error(), "requires Stream=true") {
    log.Error("programmer error: Stream flag not set for the streaming API")
}

Prevention

When it happens

Trigger: A plugin builds a ModelExecutionRequest without setting Stream (defaults false) and passes it to BaseAPIHandler.ExecuteModelStream.

Common situations: Forgetting to set Stream: true when constructing the request for the streaming API — the most common variant since false is the zero value.

Related errors


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