siyuan-note/siyuan · error

unregistered plugin service

Error message

unregistered plugin service: %s %s

What it means

ValidatePluginServiceResponse looks up the bundle's registered endpoints for one whose method and path match and that declares a PluginService schema. This error means no such plugin-service endpoint is registered, so the response cannot be validated against any contract definition.

Solutions

  1. Verify the exact method and path string against the registered endpoint definitions
  2. Ensure the endpoint schema declares Output: PluginServiceOutput with PluginServiceOptions() so PluginService is non-nil
  3. Rebuild/refresh the Bundle so it contains the newly added plugin-service endpoint

Example fix

// before
bundle.ValidatePluginServiceResponse("POST", "/plugins/demo/data", ...)
// after
bundle.ValidatePluginServiceResponse("GET", "/plugins/demo/data", ...) // matches registration
Defensive patterns

Strategy: validation

Validate before calling

registered := false
for _, ep := range bundle.Endpoints {
	if ep.Method == method && ep.Path == path && ep.PluginService != nil {
		registered = true
		break
	}
}
if !registered {
	return fmt.Errorf("endpoint %s %s is not a registered plugin service", method, path)
}

Prevention

When it happens

Trigger: Calling Bundle.ValidatePluginServiceResponse("GET", "/plugins/foo/bar", ...) where /plugins/foo/bar is not in b.Endpoints, the method differs (POST vs GET), or the endpoint exists but has no PluginService declaration (validatePluginServiceDefinition failed).

Common situations: Route typos or missing leading/trailing slashes; registering the endpoint under a different HTTP method; forgetting to declare the pluginService output when building the endpoint schema; a stale bundle built before the endpoint was added.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19). Data as JSON: /api/errors/d2f1f8e78d8bbc7f. Report an issue: GitHub.

Appendix: source

Thrown at kernel/apicontract/plugin_service_protocol.go:191

		if len(payload) > 0 {
			return fmt.Errorf("plugin service response forbids a body")
		}
		return nil
	}
	// 原始文件、代理及插件自选媒体允许任意字节,具体分支由 ValidatePluginServiceResponse 校验。
	return nil
}

func (b *Bundle) ValidatePluginServiceResponse(method, path string, mode PluginServiceMode, status int, contentType string, payload []byte) error {
	var found bool
	for _, endpoint := range b.Endpoints {
		if endpoint.Method == method && endpoint.Path == path && endpoint.PluginService != nil {
			found = true
			break
		}
	}
	if !found {
		return fmt.Errorf("unregistered plugin service: %s %s", method, path)
	}
	if err := validatePluginServiceStatus(mode, status); err != nil {
		return err
	}
	if method == "HEAD" || status < 200 || status == 204 || status == 304 {
		if len(payload) != 0 {
			return fmt.Errorf("plugin service response forbids a body")
		}
		return nil
	}
	switch mode {
	case PluginServiceEmpty:
		if len(payload) != 0 {
			return fmt.Errorf("empty plugin response contains a body")
		}
	case PluginServiceJSON, PluginServiceASCIIJSON, PluginServiceIndentedJSON, PluginServicePureJSON:
		if !json.Valid(payload) {
			return fmt.Errorf("invalid plugin JSON response")

View on GitHub (pinned to 9f775e8a12)