{"record":{"id":"52b8816356e7c45d","repo":"decolua/9router","slug":"xquik-querytype-must-be-latest-or-top","errorCode":null,"errorMessage":"Xquik queryType must be Latest or Top","messagePattern":"Xquik queryType must be Latest or Top","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"open-sse/handlers/search/callers.js","lineNumber":356,"sourceCode":"  const page = toPageNumber(params.offset, params.maxResults);\n  if (page) qp.set(\"pageno\", String(page));\n\n  return {\n    url: `${url}?${qp}`,\n    init: {\n      method: \"GET\",\n      headers: { Accept: \"application/json\" },\n    },\n  };\n}\n\nfunction buildXquikRequest(config, params) {\n  const apiKey = params.token;\n  if (!apiKey) throw new Error(\"Xquik requires an API key\");\n\n  const queryType = getProviderSetting(params, \"queryType\");\n  if (queryType && ![\"Latest\", \"Top\"].includes(queryType)) {\n    throw new Error(\"Xquik queryType must be Latest or Top\");\n  }\n\n  const qp = new URLSearchParams({\n    q: params.query,\n    limit: String(params.maxResults),\n  });\n  const cursor = getProviderSetting(params, \"cursor\");\n  if (cursor) qp.set(\"cursor\", cursor);\n  if (queryType) qp.set(\"queryType\", queryType);\n  if (params.language) qp.set(\"language\", params.language);\n\n  return {\n    url: `${resolveBaseUrl(config, params)}?${qp}`,\n    init: {\n      method: \"GET\",\n      headers: { Accept: \"application/json\", \"x-api-key\": apiKey },\n    },\n  };","sourceCodeStart":338,"sourceCodeEnd":374,"githubUrl":"https://github.com/decolua/9router/blob/90b52e06ffd666b7929554211474d01588f6b1f8/open-sse/handlers/search/callers.js#L338-L374","documentation":"buildXquikRequest validates the optional `queryType` provider setting (read from providerOptions or providerSpecificData via getProviderSetting). Xquik's upstream API only accepts 'Latest' or 'Top'; any other non-empty string is rejected with this error before a request is built.","triggerScenarios":"Passing providerOptions.queryType or providerSpecificData.queryType with a value other than 'Latest' or 'Top' (e.g. 'latest', 'recent', 'Live', 'mixed'). The check is case-sensitive.","commonSituations":"Client sends lowercase 'latest' while the API expects capitalized 'Latest'; UI/dashboard exposes a free-text field instead of a dropdown; typo like 'TopTweets' or 'trending'; stale saved settings from an older schema.","solutions":["Use exactly 'Latest' or 'Top' (capitalized) in providerOptions.queryType","Omit queryType entirely if you don't need it — it's optional and defaults upstream","Normalize the value before calling: `const qt = v ? v[0].toUpperCase() + v.slice(1).toLowerCase() : undefined` and validate against the allowed list","Check where the setting is persisted (providerSpecificData vs providerOptions) and correct the stale value"],"exampleFix":"// before\nawait search({ provider: 'xquik', query: 'ai', token, providerOptions: { queryType: 'latest' } });\n// after\nawait search({ provider: 'xquik', query: 'ai', token, providerOptions: { queryType: 'Latest' } });","handlingStrategy":"validation","validationCode":"const ALLOWED_QUERY_TYPES = ['Latest', 'Top'];\nconst qt = params.providerOptions?.queryType ?? params.providerSpecificData?.queryType;\nif (qt !== undefined && !ALLOWED_QUERY_TYPES.includes(qt)) {\n  throw new Error(`Xquik queryType must be one of ${ALLOWED_QUERY_TYPES.join(', ')}`);\n}","typeGuard":"function isValidXquikQueryType(v) {\n  return v === undefined || (typeof v === 'string' && ['Latest', 'Top'].includes(v));\n}","tryCatchPattern":"try {\n  const res = await search({ provider: 'xquik', query, token, providerOptions: { queryType } });\n} catch (err) {\n  if (err.message.includes('queryType must be')) {\n    // fall back to omitting queryType (default behavior)\n    return search({ provider: 'xquik', query, token });\n  } else throw err;\n}","preventionTips":["Use a dropdown/enum in UIs instead of free text for queryType","Normalize casing ('latest' → 'Latest') before sending","Omit queryType when you don't need it — it's optional","Mirror the allowed values from open-sse/handlers/search/callers.js rather than duplicating literals"],"tags":["validation","search","xquik","enum-value"],"backgroundTag":"invalid-enum-value","analyzedSha":"90b52e06ffd666b7929554211474d01588f6b1f8","analyzedAt":"2026-08-30T21:05:45.952Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}