{"record":{"id":"a48c46a7d4622961","repo":"decolua/9router","slug":"xquik-requires-an-api-key","errorCode":null,"errorMessage":"Xquik requires an API key","messagePattern":"Xquik requires an API key","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"open-sse/handlers/search/callers.js","lineNumber":352,"sourceCode":"  });\n  if (params.language) qp.set(\"language\", params.language);\n  if (params.timeRange && params.timeRange !== \"any\") qp.set(\"time_range\", params.timeRange);\n\n  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: {","sourceCodeStart":334,"sourceCodeEnd":370,"githubUrl":"https://github.com/decolua/9router/blob/90b52e06ffd666b7929554211474d01588f6b1f8/open-sse/handlers/search/callers.js#L334-L370","documentation":"buildXquikRequest builds the request for the Xquik (X/Twitter search) provider, which authenticates with an API key in params.token. It throws this error when the token is falsy, since the upstream endpoint requires credentials on every request.","triggerScenarios":"Calling the Xquik search route with params.token undefined/null/empty — credential not configured, blank field, or a programmatically built params object missing `token`.","commonSituations":"Xquik provider enabled without a key; key stored under another provider id; env var missing in CI/scripts; credential wiped by rotation or account deletion.","solutions":["Configure an Xquik API key for the xquik provider in the dashboard/accounts store","Pass token explicitly in the params object at the call site","Confirm the credential is saved under the correct provider id and is a non-empty string","If using env-based setup, ensure the env var is loaded before the request"],"exampleFix":"// before\nawait search({ provider: 'xquik', query: 'ai agents', maxResults: 20 });\n// after\nawait search({ provider: 'xquik', query: 'ai agents', maxResults: 20, token: process.env.XQUIK_API_KEY });","handlingStrategy":"validation","validationCode":"if (!params?.token || typeof params.token !== 'string' || !params.token.trim()) {\n  throw new Error('Xquik search requires a non-empty token');\n}","typeGuard":"function hasXquikToken(params) {\n  return typeof params?.token === 'string' && params.token.trim().length > 0;\n}","tryCatchPattern":"try {\n  const res = await search({ provider: 'xquik', query, token });\n} catch (err) {\n  if (err.message.includes('requires an API key')) {\n    // configure the Xquik key, then retry\n  } else throw err;\n}","preventionTips":["Configure the Xquik API key before enabling the provider","Preflight-check tokens for all enabled providers on startup","Ensure env vars are loaded in CI/scripts before making search calls"],"tags":["api-key","search","xquik","configuration"],"backgroundTag":"missing-api-key","analyzedSha":"90b52e06ffd666b7929554211474d01588f6b1f8","analyzedAt":"2026-08-30T21:05:45.952Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}