{"record":{"id":"dd6ad746b9caf708","repo":"siyuan-note/siyuan","slug":"frontend-capability-description-is-required-s","errorCode":null,"errorMessage":"frontend capability description is required: %s","messagePattern":"frontend capability description is required: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/agent/capability.go","lineNumber":238,"sourceCode":"\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\"\n\t\tif strings.HasPrefix(frontend.ID, \"plugin/frontend/\") {\n\t\t\tsource = \"plugin\"\n\t\t}","sourceCodeStart":220,"sourceCodeEnd":256,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/agent/capability.go#L220-L256","documentation":"buildCapabilitySet validates every frontend-provided capability before registering it as a tool. A capability whose Description field is empty or whitespace-only is rejected because the model-facing tool definition needs a usable description. The capability ID is included so the offending registration can be located.","triggerScenarios":"A frontend or plugin registers a capability with an empty Description field, e.g. passing {ID: \"plugin/frontend/foo\", Name: ..., InputSchema: ...} without Description into the capability list consumed by buildCapabilitySet.","commonSituations":"Plugin authors adding a new frontend capability but forgetting to fill in the Description; capability metadata built dynamically where a description lookup returns an empty string; JSON payloads from the frontend with a missing/empty description field.","solutions":["Set a non-empty Description on the frontend capability whose ID is named in the error","If the description comes from plugin metadata, fix the plugin's manifest/description source so it returns a real string","If a capability is not ready to describe, omit it from the frontendCapabilities list entirely instead of passing an empty description"],"exampleFix":"// before\n{ID: \"plugin/frontend/preview\", Name: \"preview\", InputSchema: schema}\n// after\n{ID: \"plugin/frontend/preview\", Name: \"preview\", Description: \"Render a live preview of the current block\", InputSchema: schema}","handlingStrategy":"validation","validationCode":"if strings.TrimSpace(cap.Description) == \"\" {\n    return fmt.Errorf(\"capability %s needs a description\", cap.ID)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Make Description a required field in any capability constructor or builder","Validate capability metadata at plugin load time, not only at registration into the kernel","Centralize capability creation in one helper that enforces non-empty ID, Name, and Description"],"tags":["go","validation","agent","capabilities"],"backgroundTag":"empty-required-field","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"}