{"record":{"id":"e407445643a2d0a1","repo":"multica-ai/multica","slug":"search-skills-w","errorCode":null,"errorMessage":"search skills: %w","messagePattern":"search skills: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/cmd/multica/cmd_skill.go","lineNumber":612,"sourceCode":"\nfunc runSkillSearch(cmd *cobra.Command, args []string) error {\n\tclient, err := newAPIClient(cmd)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tquery := strings.TrimSpace(args[0])\n\tif query == \"\" {\n\t\treturn fmt.Errorf(\"query is required\")\n\t}\n\n\tctx, cancel := context.WithTimeout(context.Background(), cli.AtLeastAPITimeout(60*time.Second))\n\tdefer cancel()\n\n\tvar results []map[string]any\n\tpath := \"/api/skills/search?q=\" + url.QueryEscape(query)\n\tif err := client.GetJSON(ctx, path, &results); err != nil {\n\t\treturn fmt.Errorf(\"search skills: %w\", err)\n\t}\n\n\toutput, _ := cmd.Flags().GetString(\"output\")\n\tif output == \"json\" {\n\t\treturn cli.PrintJSON(os.Stdout, results)\n\t}\n\n\theaders := []string{\"NAME\", \"URL\", \"SOURCE\", \"INSTALLS\", \"DESCRIPTION\"}\n\trows := make([][]string, 0, len(results))\n\tfor _, result := range results {\n\t\trows = append(rows, []string{\n\t\t\tstrVal(result, \"name\"),\n\t\t\tstrVal(result, \"url\"),\n\t\t\tstrVal(result, \"source\"),\n\t\t\tstrVal(result, \"install_count\"),\n\t\t\tstrVal(result, \"description\"),\n\t\t})\n\t}","sourceCodeStart":594,"sourceCodeEnd":630,"githubUrl":"https://github.com/multica-ai/multica/blob/2c0912b6ec764b373d44eeea1e80f0d9f11ab417/server/cmd/multica/cmd_skill.go#L594-L630","documentation":"Returned by `multica skill search` when GET `/api/skills/search?q=<query>` fails. The query is URL-escaped client-side, so encoding is not the issue; the wrapped cause is transport failure, timeout (60s budget covers the server's search/index work), auth rejection, or a server-side search error (e.g. index not built).","triggerScenarios":"Server down or wrong --api-url; auth token expired (401); search index cold or corrupted causing 500; extremely broad query (single common character) overloading the server until the context deadline expires.","commonSituations":"First search after server startup before the index warms; CLI configured for a stale environment; large skill catalog with a one-character query; transient network blip between CLI and server.","solutions":["Verify basic API health with `multica skill list` — if that works, the failure is specific to search.","Retry once; index warm-up and transient timeouts often clear immediately.","Use a more specific query to reduce server-side search cost.","If list works but every search 500s, check server logs for index-related errors."],"exampleFix":"# before\nmultica skill search a   # times out over huge catalog\n\n# after\nmultica skill list > /dev/null && multica skill search \"ascii tables\"","handlingStrategy":"retry","validationCode":"multica skill list > /dev/null || exit 1   # pre-flight API reachability\n[ \"${#QUERY}\" -ge 2 ] || { echo 'use a query of 2+ chars'; exit 1; }","typeGuard":null,"tryCatchPattern":"Retry once on timeout-shaped errors (cold index, transient load); do not retry 401/403 (fix auth) or persistent 500s (inspect server logs for the search index). Wrap the CLI call in a script, capture stderr, and branch on status keywords before deciding to retry.","preventionTips":["Warm the API with a cheap call (skill list) before searching right after server start.","Keep queries reasonably specific to bound server-side search cost.","Reuse one authenticated session/context for repeated searches to avoid auth flakes."],"tags":["cli","http","search","skill"],"backgroundTag":null,"analyzedSha":"2c0912b6ec764b373d44eeea1e80f0d9f11ab417","analyzedAt":"2026-08-15T13:25:18.241Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}