router-for-me/CLIProxyAPI · error

model execution failed with status %d

Error message

model execution failed with status %d

What it means

modelExecutionError converts an upstream execution result into an error when the executor returned an ErrorMessage with no Go error object but a positive HTTP status code. The %d is the upstream HTTP status (401, 429, 500, ...) of the nested model call requested via host.model.execute.

Source

Thrown at internal/pluginhost/host_callbacks.go:317

		Stream:                  req.Stream,
		Body:                    append([]byte(nil), req.Body...),
		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 != "" {

View on GitHub (pinned to 78f0c4079e)

Solutions

  1. Map the status: 401/403 -> refresh or fix credentials for the provider; 429 -> slow down or reduce nested calls; 5xx -> retry with backoff or switch provider.
  2. Check the host logs for the same request: the executor usually logs the upstream response body with more detail.
  3. For plugins, cache or limit host.model.execute calls to avoid amplifying rate limits.
  4. Verify the model name passed in the nested request exists on the target provider.
Defensive patterns

Strategy: retry

Validate before calling

// Pre-flight credentials/quota before issuing nested model calls
if !providerHasValidCredential(provider) {
    return fmt.Errorf("skip nested call: provider %s credentials invalid", provider)
}

Type guard

func retryableModelStatus(statusCode int) bool {
    return statusCode == 429 || statusCode >= 500
}

Try / catch

resp, err := host.ModelExecute(ctx, req)
if err != nil {
    if status, ok := extractStatus(err); ok { // parse "failed with status %d"
        if status == 401 || status == 403 {
            return refreshCredentialsAndRetry(ctx, req)
        }
        if status == 429 || status >= 500 {
            return backoffRetry(ctx, req, 3)
        }
    }
    return err
}

Prevention

When it happens

Trigger: A plugin's host.model.execute call where the upstream provider returned an error status: 401/403 from bad credentials, 429 from rate limiting, 5xx provider outages. The executor produced only a status code without a structured error.

Common situations: Expired or invalid API keys on the routed provider; rate limits hit because the plugin issues nested model calls on top of user traffic; upstream outage; model not available for the account.

Related errors


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