siyuan-note/siyuan · error
invalid frontend capability ID: %s
Error message
invalid frontend capability ID: %s
What it means
capability.go validates each frontend capability id with validFrontendCapabilityID(). The id must be exactly 'native/frontend/<name>' (3 segments) or 'plugin/frontend/<owner>/<name>' (4 segments), with no empty segments and total length <= 512. Any other shape returns the formatted error naming the offending id.
Source
Thrown at kernel/agent/capability.go:216
Description: tool.Description,
Source: source,
OwnerID: tool.OwnerID,
OwnerName: tool.OwnerName,
Runtime: runtime,
Tool: tool,
Validator: validator,
InputSchema: tool.InputSchema,
OutputSchema: tool.OutputSchema,
AccessContext: accessContext,
}
if err := set.add(registration); err != nil {
return nil, err
}
}
for _, frontend := range frontendCapabilities {
if !validFrontendCapabilityID(frontend.ID) {
return nil, fmt.Errorf("invalid frontend capability ID: %s", frontend.ID)
}
if strings.TrimSpace(frontend.Description) == "" {
return nil, fmt.Errorf("frontend capability description is required: %s", frontend.ID)
}
if !capabilityAllowed(frontend.ID, accessContext) {
continue
}
validationTool := &tools.Tool{
Name: frontendCapabilityModelName(frontend.ID),
Description: frontend.Description,
InputSchema: frontend.InputSchema,
OutputSchema: frontend.OutputSchema,
}
validator, err := tools.CompileToolValidator(validationTool)
if err != nil {
return nil, fmt.Errorf("invalid frontend capability [%s]: %w", frontend.ID, err)
}
source := "native"View on GitHub (pinned to 251596fc0d)
Solutions
- Format ids strictly as 'native/frontend/<name>' or 'plugin/frontend/<owner>/<name>' with non-empty owner/name.
- Validate the id client-side with the same segment rule before sending it to the kernel.
- Trim owner/name and reject empty values at registration time in the frontend (Plugin.addAgentCapability already does encodeURIComponent — supply non-empty raw values).
- Keep the total id length under 512 characters.
Example fix
// before
id := fmt.Sprintf('plugin/frontend/%s/', owner) // empty name segment
// after
if owner == '' || name == '' { return errors.New('owner and name required') }
id := fmt.Sprintf('plugin/frontend/%s/%s', owner, name) Defensive patterns
Strategy: validation
Validate before calling
func validID(id string) bool {
if len(id) > 512 { return false }
p := strings.Split(id, '/')
return (len(p) == 3 && p[0]=='native' && p[1]=='frontend' && p[2] != '') ||
(len(p) == 4 && p[0]=='plugin' && p[1]=='frontend' && p[2] != '' && p[3] != '')
} Try / catch
if err := buildCapabilitySet(...); err != nil {
if strings.Contains(err.Error(), 'invalid frontend capability ID') { /* log offending id, skip */ }
return err
} Prevention
- Always format ids as 'native/frontend/<name>' or 'plugin/frontend/<owner>/<name>'.
- Trim and reject empty owner/name before constructing the id.
- Keep total id length under 512 characters.
- Share the id-format validator between frontend and kernel.
When it happens
Trigger: A frontend capability is registered with an id missing a segment (e.g. 'plugin/frontend/' with empty owner or name), using a wrong prefix ('frontend/x/y'), extra slashes, a >512 char id, or a name that URI-decodes to empty.
Common situations: Plugin uses encodeURIComponent on an already-encoded name producing extra slashes; capability id constructed from user input that was blank; refactor changed the prefix constant; URIDecode on the server yields an empty trailing segment.
Related errors
- frontend capability description is required: %s
- invalid frontend capability [%s]: %w
- registerCapability requires 3 arguments: name, config, handl
- capability name must not be empty
- config.description must not be empty
AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12).
Data as JSON: /api/errors/edcef24287c3b2ed.
Report an issue: GitHub.