{"record":{"id":"edcef24287c3b2ed","repo":"siyuan-note/siyuan","slug":"invalid-frontend-capability-id-s","errorCode":null,"errorMessage":"invalid frontend capability ID: %s","messagePattern":"invalid frontend capability ID: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/agent/capability.go","lineNumber":235,"sourceCode":"\t\t\tDescription:   tool.Description,\n\t\t\tSource:        source,\n\t\t\tOwnerID:       tool.OwnerID,\n\t\t\tOwnerName:     tool.OwnerName,\n\t\t\tRuntime:       runtime,\n\t\t\tTool:          tool,\n\t\t\tValidator:     validator,\n\t\t\tInputSchema:   tool.InputSchema,\n\t\t\tOutputSchema:  tool.OutputSchema,\n\t\t\tAccessContext: accessContext,\n\t\t}\n\t\tif err := set.add(registration); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\n\tfor _, frontend := range frontendCapabilities {\n\t\tif !validFrontendCapabilityID(frontend.ID) {\n\t\t\treturn nil, fmt.Errorf(\"invalid frontend capability ID: %s\", frontend.ID)\n\t\t}\n\t\tif strings.TrimSpace(frontend.Description) == \"\" {\n\t\t\treturn nil, fmt.Errorf(\"frontend capability description is required: %s\", frontend.ID)\n\t\t}\n\t\tif !capabilityAllowed(frontend.ID, accessContext) {\n\t\t\tcontinue\n\t\t}\n\t\tvalidationTool := &tools.Tool{\n\t\t\tName:         frontendCapabilityModelName(frontend.ID),\n\t\t\tDescription:  frontend.Description,\n\t\t\tInputSchema:  frontend.InputSchema,\n\t\t\tOutputSchema: frontend.OutputSchema,\n\t\t}\n\t\tvalidator, err := tools.CompileToolValidator(validationTool)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"invalid frontend capability [%s]: %w\", frontend.ID, err)\n\t\t}\n\t\tsource := \"native\"","sourceCodeStart":217,"sourceCodeEnd":253,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/agent/capability.go#L217-L253","documentation":"Raised by buildCapabilitySet when a frontend capability declared by a plugin fails the validFrontendCapabilityID check. Every frontend capability must use a recognized/valid ID format from the allowed capability namespace; an unknown or malformed ID aborts capability-set construction so unregistered capabilities can never be exposed to or invoked by the model.","triggerScenarios":"In capability.go (~line 235): during buildCapabilitySet, iterating frontendCapabilities, a capability's frontend.ID does not pass validFrontendCapabilityID — e.g. a plugin registers a tool with a made-up or wrongly formatted/renamed ID, or a renamed built-in ID is still referenced by stale plugin code.","commonSituations":"A plugin declares a custom frontend tool whose ID is not in the valid capability registry; a SiYuan upgrade renamed/retired a capability ID while an outdated plugin still declares the old one; a typo in a capability ID string in plugin code; copying a sample plugin and editing the ID to an unsupported value.","solutions":["Change the plugin's frontend capability ID to a value accepted by validFrontendCapabilityID (use a registered built-in ID or the sanctioned custom-ID format).","Update the plugin to the current API version if a capability ID was renamed or removed in a recent release.","Disable or uninstall the offending plugin to restore agent functionality.","Check plugin code for typos in the ID string and against the plugin-sample reference implementation for the correct declaration."],"exampleFix":"// before: plugin declares an arbitrary capability ID\nplugin.addFrontendCapability({ id: \"myCustomRunner\", description: \"Run tasks\" })\n// after: use a valid registered ID\nplugin.addFrontendCapability({ id: \"queryBlockDoc\", description: \"Query blocks by SQL\" })","handlingStrategy":"validation","validationCode":"function hasValidCapabilityID(cap) {\n  return VALID_FRONTEND_CAPABILITY_IDS.includes(cap.id) && typeof cap.description === \"string\" && cap.description.trim() !== \"\"\n}","typeGuard":null,"tryCatchPattern":"caps, err := buildCapabilitySet(frontendCapabilities, accessContext)\nif err != nil {\n    // identify the offending plugin by the ID in the message and disable/update it\n}","preventionTips":["Only declare frontend capabilities whose IDs pass validFrontendCapabilityID.","After each SiYuan upgrade, check plugins for renamed/removed capability IDs.","Test plugin capability registration against buildCapabilitySet before release.","Copy capability declarations from plugin-sample rather than inventing IDs."],"tags":["capabilities","plugins","validation","agent"],"backgroundTag":"invalid-identifier-format","analyzedSha":"9f775e8a12daef8255556097396f9b2739078892","analyzedAt":"2026-09-19T03:17:15.984Z","contentChangedAt":"2026-09-19T03:17:15.984Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}