{"record":{"id":"17b5d83b19bd913d","repo":"Tencent/WeKnora","slug":"query-is-empty-17b5d8","errorCode":null,"errorMessage":"query is empty","messagePattern":"query is empty","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"internal/infrastructure/web_search/keenable.go","lineNumber":68,"sourceCode":"\t\tbaseURL: defaultKeenableBaseURL,\n\t\tapiKey:  params.APIKey,\n\t}, nil\n}\n\n// Name returns the provider name\nfunc (p *KeenableProvider) Name() string {\n\treturn \"keenable\"\n}\n\n// Search performs a web search using the Keenable Search API.\nfunc (p *KeenableProvider) Search(\n\tctx context.Context,\n\tquery string,\n\tmaxResults int,\n\tincludeDate bool,\n) ([]*types.WebSearchResult, error) {\n\tif len(query) == 0 {\n\t\treturn nil, fmt.Errorf(\"query is empty\")\n\t}\n\tif maxResults <= 0 {\n\t\tmaxResults = defaultKeenableResults\n\t}\n\n\t// Keyless by default; a configured key switches to the authenticated path.\n\tpath := \"/v1/search/public\"\n\tif p.apiKey != \"\" {\n\t\tpath = \"/v1/search\"\n\t}\n\tendpoint := p.baseURL + path\n\tlogger.Infof(ctx, \"[WebSearch][Keenable] query=%q maxResults=%d url=%s\", query, maxResults, endpoint)\n\n\tbodyBytes, err := json.Marshal(keenableSearchRequest{Query: query, Mode: \"pro\"})\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to marshal request: %w\", err)\n\t}\n","sourceCodeStart":50,"sourceCodeEnd":86,"githubUrl":"https://github.com/Tencent/WeKnora/blob/988cbb03305e055d8ebb7d46d9ac6cc0803cd074/internal/infrastructure/web_search/keenable.go#L50-L86","documentation":"KeenableProvider.Search guards against an empty query string and returns this error before issuing the HTTP POST. It mirrors the same guard as the Google provider so callers get a consistent, immediate failure instead of a meaningless remote search.","triggerScenarios":"Calling keenable.Search(ctx, \"\", maxResults, includeDate) — empty or never-populated query (tests TestKeenableProvider_Search_* exercise this path).","commonSituations":"Caller passes untrimmed user input that is empty; upstream NLU produced no terms; a variable defaulting to \"\" was forwarded directly.","solutions":["Trim and validate the query in the calling code before calling Search.","Skip search flow entirely for empty queries and respond with a prompt for more input.","Add a unit test covering the empty-query path of your integration layer."],"exampleFix":"// before\nresults, err := keenable.Search(ctx, query, 10, false)\n// after\nquery = strings.TrimSpace(query)\nif query == \"\" {\n    return nil, errors.New(\"cannot search: query is empty\")\n}\nresults, err := keenable.Search(ctx, query, 10, false)","handlingStrategy":"validation","validationCode":"q := strings.TrimSpace(userQuery)\nif q == \"\" {\n    return nil, errors.New(\"cannot perform keenable search: empty query\")\n}\nreturn keenable.Search(ctx, q, maxResults, false)","typeGuard":null,"tryCatchPattern":"results, err := keenable.Search(ctx, q, n, false)\nif err != nil && err.Error() == \"query is empty\" {\n    return nil, errors.New(\"please provide search terms\")\n}","preventionTips":["Validate query non-empty (and trimmed) before any provider call","Handle empty upstream NLU output before it reaches the search layer","Cover empty-query branches in unit tests","Share one query-normalization helper across all search providers"],"tags":["validation","keenable","web-search","input-validation"],"backgroundTag":"empty-required-parameter","analyzedSha":"988cbb03305e055d8ebb7d46d9ac6cc0803cd074","analyzedAt":"2026-09-02T14:41:08.344Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}