{"record":{"id":"db1a016fbed1b995","repo":"koala73/worldmonitor","slug":"wikidata-request-failed-with-status-response-sta","errorCode":null,"errorMessage":"Wikidata request failed with status ${response.status}","messagePattern":"Wikidata request failed with status (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"server/worldmonitor/intelligence/v1/get-country-facts.ts","lineNumber":167,"sourceCode":"\nasync function queryWikidata(sparql: string): Promise<WikidataBinding[]> {\n  const url = `https://query.wikidata.org/sparql?format=json&query=${encodeURIComponent(sparql)}`;\n\n  for (let attempt = 0; attempt < WIKIDATA_ATTEMPTS; attempt += 1) {\n    let response: Response;\n    try {\n      response = await fetch(url, {\n        headers: { 'User-Agent': WIKIMEDIA_UA, Accept: 'application/json' },\n        signal: AbortSignal.timeout(UPSTREAM_TIMEOUT),\n      });\n    } catch (error) {\n      if (attempt === WIKIDATA_ATTEMPTS - 1) throw error;\n      continue;\n    }\n    if (!response.ok) {\n      const retryable = response.status === 429 || response.status >= 500;\n      if (retryable && attempt < WIKIDATA_ATTEMPTS - 1) continue;\n      throw new Error(`Wikidata request failed with status ${response.status}`);\n    }\n\n    try {\n      const data = (await response.json()) as WikidataResponse;\n      return data.results?.bindings ?? [];\n    } catch (error) {\n      if (attempt === WIKIDATA_ATTEMPTS - 1) throw error;\n    }\n  }\n\n  throw new Error('Wikidata request failed');\n}\n\nfunction parseWikidataFacts(bindings: WikidataBinding[]): WikiResult | null {\n  if (bindings.length === 0) return null;\n\n  const firstLabel = (field: keyof WikidataBinding): string => {\n    for (const binding of bindings) {","sourceCodeStart":149,"sourceCodeEnd":185,"githubUrl":"https://github.com/koala73/worldmonitor/blob/9361220cc013571781071f0206e4d80fd14b2f7f/server/worldmonitor/intelligence/v1/get-country-facts.ts#L149-L185","documentation":"queryWikidata fetches country facts from the Wikidata SPARQL/REST endpoint with WIKIDATA_ATTEMPTS tries. Retryable failures (429 or 5xx) are retried, but when the final attempt still returns a non-ok status — or the status is non-retryable like 400/403/404 — it throws Error 'Wikidata request failed with status <status>'. This surfaces upstream Wikidata rejection to the country-facts caller.","triggerScenarios":"The final fetch to the Wikidata endpoint responds with a non-ok status: non-retryable 400/401/403/404 immediately, or a 429/5xx that persists through all WIKIDATA_ATTEMPTS retries.","commonSituations":"Wikidata rate limiting the server IP (429 sustained); Wikidata outage (502/503) lasting longer than the retry budget; malformed SPARQL query returning 400 after a code change; User-Agent blocked by Wikimedia policy (403).","solutions":["Check the status in the message: 400 means fix the query, 403 means fix the User-Agent, 429 means back off, 5xx means retry later or check Wikidata status","Increase WIKIDATA_ATTEMPTS or add exponential backoff between attempts for sustained 429/5xx","Ensure requests send a descriptive User-Agent header per Wikimedia UA policy","Add a fallback path (cached facts or a second data source) so country facts survive Wikidata unavailability"],"exampleFix":"// before\nthrow new Error(`Wikidata request failed with status ${response.status}`);\n// after\nconst body = await response.text().catch(() => '');\nlogger.warn('wikidata failed', response.status, body.slice(0, 200));\nthrow new Error(`Wikidata request failed with status ${response.status}`);","handlingStrategy":"retry","validationCode":"// Validate request inputs before hitting Wikidata\nif (!countryCode || !/^[A-Z]{2}$/.test(countryCode)) throw new Error('invalid country code');","typeGuard":"function isWikidataStatusError(e: unknown): e is Error & { status?: number } {\n  return e instanceof Error && /^Wikidata request failed with status \\d+$/.test(e.message);\n}","tryCatchPattern":"try {\n  bindings = await queryWikidata(sparql);\n} catch (e) {\n  if (isWikidataStatusError(e) && /status (429|5\\d\\d)/.test(e.message)) {\n    return serveCachedFacts(countryCode); // stale-but-available\n  }\n  throw e;\n}","preventionTips":["Send a compliant descriptive User-Agent on all Wikimedia requests","Use exponential backoff and a generous attempt count for 429/5xx","Cache successful bindings with a TTL to survive upstream outages","Log status + response body snippet on failure for quick diagnosis"],"tags":["wikidata","http","retry","upstream"],"backgroundTag":"upstream-http-error","analyzedSha":"9361220cc013571781071f0206e4d80fd14b2f7f","analyzedAt":"2026-09-01T10:32:37.851Z","contentChangedAt":"2026-09-01T10:32:37.851Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}