router-for-me/CLIProxyAPI · error

plugin call failed

Error message

plugin call failed

What it means

The plugin returned an envelope with ok=false but no Error object at all, so decodeEnvelopeResult can only report the generic 'plugin call failed'. The plugin failed without explaining why — typically a stubbed method, a defensive false return, or a version that omits error details.

Source

Thrown at internal/pluginhost/rpc_client.go:315

		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. Check the plugin's logs/stderr for the real failure reason at that timestamp
  2. If you own the plugin, always populate Envelope.Error.Message on failure
  3. Verify the plugin implements the method being called (version/feature check)

Example fix

// plugin: before
return marshalRPCEnvelope(nil) // with ok=false and no error

// plugin: after
return pluginabi.NewErrorEnvelope(fmt.Errorf("translate: unsupported model %s", model))
Defensive patterns

Strategy: try-catch

Try / catch

out, err := callPlugin[T](ctx, client, method, req)
if err != nil && err.Error() == "plugin call failed" {
    log.Errorf("plugin %s failed without detail; check plugin stderr/logs", method)
}

Prevention

When it happens

Trigger: Plugin handler returns an envelope {ok:false} with a nil/absent error field for any method invoked via callPlugin.

Common situations: Plugin method not implemented (returns bare failure); plugin built from a skeleton/template; error-construction path in the plugin dropped the Error field.

Related errors


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