router-for-me/CLIProxyAPI · error
model execution failed
Error message
model execution failed
What it means
The catch-all branch of modelExecutionError: the executor returned a non-nil ErrorMessage with neither an Error object nor a positive status code. The nested model call failed, but the executor gave no structured detail, so the host can only report generic failure to the plugin.
Source
Thrown at internal/pluginhost/host_callbacks.go:319
Headers: cloneHeader(req.Headers),
Query: cloneValues(req.Query),
Alt: req.Alt,
SkipInterceptorPluginID: skipPluginID,
SkipRouterPluginID: skipPluginID,
}
}
func modelExecutionError(errMsg *interfaces.ErrorMessage) error {
if errMsg == nil {
return nil
}
if errMsg.Error != nil {
return errMsg.Error
}
if errMsg.StatusCode > 0 {
return fmt.Errorf("model execution failed with status %d", errMsg.StatusCode)
}
return fmt.Errorf("model execution failed")
}
func (h *Host) callHostLog(ctx context.Context, request []byte) ([]byte, error) {
var req rpcHostLogRequest
if errUnmarshal := json.Unmarshal(request, &req); errUnmarshal != nil {
return nil, fmt.Errorf("decode host log request: %w", errUnmarshal)
}
ctx = h.resolveCallbackContext(req.HostCallbackID, ctx)
message := strings.TrimSpace(req.Message)
if message == "" {
message = "plugin log"
}
fields := log.Fields{}
for key, value := range req.Fields {
key = strings.TrimSpace(key)
if key != "" {
fields[key] = value
}View on GitHub (pinned to 78f0c4079e)
Solutions
- Enable debug logging around the nested call to see which executor produced the empty ErrorMessage.
- If you own the executor/plugin code, always set either Error or StatusCode on failures instead of an empty ErrorMessage.
- Retry once to rule out a transient canceled execution; if reproducible, inspect the executor's failure paths.
- Update executor plugin and host to matching versions.
Example fix
// executor/plugin side, before
return resp, interfaces.ErrorMessage{} // failure with no detail
// after
return resp, interfaces.ErrorMessage{StatusCode: http.StatusBadGateway, Error: fmt.Errorf("upstream call failed")} Defensive patterns
Strategy: retry
Type guard
func detailedModelError(errMsg *interfaces.ErrorMessage) bool {
return errMsg != nil && (errMsg.Error != nil || errMsg.StatusCode > 0)
} Try / catch
resp, err := host.ModelExecute(ctx, req)
if err != nil && strings.Contains(err.Error(), "model execution failed") && !strings.Contains(err.Error(), "status") {
// detail-less failure: single retry to rule out a transient abort, then report upstream
return retryOnceThenReport(ctx, req, err)
} Prevention
- Executor implementations should always populate Error or StatusCode on failure.
- Log the request context when this occurs to identify which executor produced the empty ErrorMessage.
When it happens
Trigger: host.model.execute returning an ErrorMessage with all fields zero: an executor implementation bug, an aborted/canceled execution reported without status, or an internal path that builds ErrorMessage{} without filling cause or code.
Common situations: Custom executor plugins that signal failure with an empty ErrorMessage; race where execution is canceled mid-flight and the error is assembled incompletely; version skew between executor interface expectations.
Related errors
- model execution failed with status %d
- host model executor is unavailable
- auth provider panic: %v
- auth provider %s returned auth without provider
- auth provider %s returned invalid auth data
AI-assisted analysis of router-for-me/CLIProxyAPI@78f0c4079e (2026-08-15).
Data as JSON: /api/errors/3c2f9baf3a466eef.
Report an issue: GitHub.