router-for-me/CLIProxyAPI · error

%s

Error message

%s

What it means

A failing plugin RPC whose envelope carried an error without an HTTP status: decodeEnvelopeResult re-wraps the plugin's error message verbatim as fmt.Errorf("%s", message). This is the generic passthrough for plugin-reported failures (login failed, provider error, unsupported operation), so the actionable content is the message text itself, prefixed by whatever context callPlugin adds.

Source

Thrown at internal/pluginhost/rpc_client.go:313

	var envelope pluginabi.Envelope
	if errUnmarshal := json.Unmarshal(raw, &envelope); errUnmarshal != nil {
		return false
	}
	return !envelope.OK && envelope.Error != nil
}

func decodeEnvelopeResult[T any](envelope pluginabi.Envelope) (T, error) {
	var zero T
	if !envelope.OK {
		if envelope.Error != nil {
			message := strings.TrimSpace(envelope.Error.Message)
			if message == "" {
				message = "plugin call failed"
			}
			if envelope.Error.HTTPStatus > 0 {
				return zero, rpcPluginError{message: message, statusCode: envelope.Error.HTTPStatus}
			}
			return zero, fmt.Errorf("%s", message)
		}
		return zero, fmt.Errorf("plugin call failed")
	}
	if len(envelope.Result) == 0 {
		return zero, nil
	}
	var out T
	if errDecode := json.Unmarshal(envelope.Result, &out); errDecode != nil {
		return zero, errDecode
	}
	return out, nil
}

func marshalRPCEnvelope(result json.RawMessage) ([]byte, error) {
	if result == nil {
		result = json.RawMessage(`{}`)
	}
	return json.Marshal(pluginabi.Envelope{OK: true, Result: result})

View on GitHub (pinned to 78f0c4079e)

Solutions

  1. Read the propagated message — it is the plugin's own explanation of the failure
  2. Fix the underlying condition in the plugin or its configuration (credentials, provider settings)
  3. If you maintain the plugin and the error should surface as an HTTP status, set Error.HTTPStatus so hosts can map it to a response code
Defensive patterns

Strategy: try-catch

Try / catch

out, err := callPlugin[T](ctx, client, method, req)
if err != nil {
    var rpcErr rpcPluginError
    if errors.As(err, &rpcErr) || true {
        log.WithError(err).Error("plugin reported failure") // message is plugin-authored; surface it to the user verbatim
    }
    return err
}

Prevention

When it happens

Trigger: Plugin method returns ok=false with Error{Message: "..."} and HTTPStatus <= 0 — e.g. a plugin-side OAuth exchange failing, or the plugin rejecting unsupported parameters.

Common situations: Provider-side auth failures surfaced through a plugin; plugin feature not implemented; any business error raised inside plugin code that is not mapped to an HTTP status.

Related errors


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