siyuan-note/siyuan · error
undeclared plugin admission status
Error message
undeclared plugin admission status
What it means
When a plugin-service variant declares admission mode, the HTTP status must be one of the statuses registered in the plugin-service definition's AdmissionStatuses (400, 404, 500, 503 per PluginServiceOptions). This error means validatePluginServiceStatus saw admission mode with a status outside that declared set, so the admission response is not contract-conformant.
Solutions
- Return only one of the declared admission statuses: 400, 404, 500, or 503
- If the desired rejection code differs, use a different variant (e.g. PluginServiceJSON with that status) instead of admission mode
- If the contract itself should allow the status, update the AdmissionStatuses declaration in PluginServiceOptions and the validation switch together
Example fix
// before StreamPluginService(PluginServiceAdmission, 403, serve) // after StreamPluginService(PluginServiceAdmission, 400, serve)
Defensive patterns
Strategy: validation
Validate before calling
allowed := []int{400, 404, 500, 503}
if mode == apicontract.PluginServiceAdmission && !slices.Contains(allowed, status) {
return fmt.Errorf("admission status %d not in %v", status, allowed)
} Try / catch
defer func() {
if rec := recover(); rec != nil {
log.Printf("invalid admission status: %v", rec)
}
}() // around StreamPluginService(PluginServiceAdmission, ...) Prevention
- Restrict admission responses to 400/404/500/503
- Use admission mode only for gate/reject decisions; use other variants for success paths
- Check the AdmissionStatuses field in PluginServiceOptions before adding new codes
When it happens
Trigger: Calling StreamPluginService(PluginServiceAdmission, status, serve) or Bundle.ValidatePluginServiceResponse(..., PluginServiceAdmission, status, ...) with any status other than 400, 404, 500, or 503 (e.g. 200 or 401).
Common situations: Plugin authors want to reject a request with a custom admission code like 403 or 422; they return a success status (200) from an admission gate by mistake; the admission statuses list was changed in the contract but the plugin still sends old codes.
Related errors
- invalid plugin redirect status
- invalid plugin SSE status
- invalid plugin WebSocket status
- empty plugin response contains a body
- invalid plugin service HTTP status
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/2488b4190f738c3e.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/apicontract/plugin_service_protocol.go:150
func validatePluginServiceStatus(mode PluginServiceMode, status int) error {
if status < 100 || status > 999 {
return fmt.Errorf("invalid plugin service HTTP status: %d", status)
}
known := false
for _, variant := range PluginServiceOptions().PluginService.Variants {
if variant.Mode == mode {
known = true
break
}
}
if !known {
return fmt.Errorf("unknown plugin service mode: %s", mode)
}
switch mode {
case PluginServiceAdmission:
if status != 400 && status != 404 && status != 500 && status != 503 {
return fmt.Errorf("undeclared plugin admission status")
}
case PluginServiceRedirect:
if status != 201 && (status < 300 || status > 308) {
return fmt.Errorf("invalid plugin redirect status")
}
case PluginServiceWebSocket:
if status != 101 && status != 400 && status != 500 {
return fmt.Errorf("invalid plugin WebSocket status")
}
case PluginServiceSSE:
if status != 200 && status != 500 {
return fmt.Errorf("invalid plugin SSE status")
}
}
return nil
}
func (b *Bundle) validatePluginServiceHTTPResponse(endpoint EndpointSchema, status int, contentType string, payload []byte) error {View on GitHub (pinned to 9f775e8a12)