{"record":{"id":"3aab6759a5910276","repo":"pot-app/pot-desktop","slug":"http-request-error-http-status-res-status-js","errorCode":null,"errorMessage":"Http Request Error\nHttp Status: ${res.status}\n${JSON.stringify(res.data)}","messagePattern":"Http Request Error\nHttp Status: (.+?)\n(.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/services/translate/cambridge_dict/index.jsx","lineNumber":53,"sourceCode":"    if (Language.auto === from) {\n        from = tryDetectLanguage(text) ?? from;\n    }\n    // only supports English word translation\n    if (from !== Language.en || to === undefined || to === from || text.split(' ').length > 1) {\n        return '';\n    }\n\n    const url = `https://dictionary.cambridge.org/search/direct/?datasetsearch=${from}-${to}&q=${text}`;\n    let res = await fetch(url, {\n        method: 'GET',\n        headers: {\n            'Content-Type': 'text/html;charset=UTF-8',\n        },\n        responseType: 2,\n    });\n\n    if (!res.ok) {\n        throw new Error(`Http Request Error\\nHttp Status: ${res.status}\\n${JSON.stringify(res.data)}`);\n    }\n    const doc = new DOMParser().parseFromString(res.data, 'text/html');\n    const entryNodes = doc.querySelectorAll('.pr.entry-body__el');\n    if (entryNodes.length === 0) {\n        throw new Error(`Words not yet included: ${text}`);\n    }\n\n    const resultMap = [...entryNodes].reduce((dict, entryNode) => {\n        const wordTranslateResult = dict['result'] || new WordTranslateResult([], []);\n\n        if (wordTranslateResult.pronunciations.length === 0) {\n            const pronunciationNodes = entryNode.querySelectorAll('.dpron-i');\n            const pronunciations = [...pronunciationNodes].map((pronunciationNode) => {\n                const region = pronunciationNode.querySelector('.region').innerText;\n                const symbol = pronunciationNode.querySelector('.pron').innerText;\n                let voice = pronunciationNode.querySelector('.daud source').src;\n                voice = voice.replace(/^https?:\\/\\/[^/]+/, 'https://dictionary.cambridge.org');\n                voice = voice.replace(/^tauri:\\/\\/[^/]+/, 'https://dictionary.cambridge.org');","sourceCodeStart":35,"sourceCodeEnd":71,"githubUrl":"https://github.com/pot-app/pot-desktop/blob/594d32ede96acd106b0256deaa8bb440ffcdff40/src/services/translate/cambridge_dict/index.jsx#L35-L71","documentation":"The Cambridge Dictionary translate service throws this when the HTTP response from dictionary.cambridge.org comes back with a non-2xx status. It wraps the status code and the raw response body in the message so the developer can see exactly what the server rejected and why. It is a generic guard for any upstream HTTP failure (network-level errors are thrown separately by the Tauri fetch).","triggerScenarios":"Calling translate(text, from, to) in src/services/translate/cambridge_dict/index.jsx:34 when the GET to https://dictionary.cambridge.org/search/direct/?datasetsearch=<from>-<to>&q=<text> returns res.ok === false (e.g. 403 bot-block, 429 rate limit, 5xx outage).","commonSituations":"Cambridge CDN/WAF blocks the request (no browser User-Agent), the user is offline or behind a proxy that returns an error page, Cambridge changes its URL scheme, or rate limiting kicks in after many dictionary lookups in a short time.","solutions":["Check the status code in the message: 403/429 usually means bot detection or rate limiting — retry later or add a valid User-Agent header in the fetch call.","Verify network/proxy connectivity to dictionary.cambridge.org in a browser; if blocked, fix proxy/VPN settings.","5xx statuses mean a Cambridge-side outage — wait and retry.","Confirm the `from`/`to` language pair is a valid Cambridge dataset (e.g. en-zh); invalid pairs can yield 4xx."],"exampleFix":"// before\nconst res = await fetch(url, { method: 'GET', headers: { 'Content-Type': 'text/html;charset=UTF-8' }, responseType: 2 });\n// after\nconst res = await fetch(url, {\n  method: 'GET',\n  headers: {\n    'Content-Type': 'text/html;charset=UTF-8',\n    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Chrome/120 Safari/537.36',\n  },\n  responseType: 2,\n});","handlingStrategy":"try-catch","validationCode":"const isSingleEnglishWord = (text) => /^[A-Za-z][A-Za-z'-]*$/.test(text.trim());\nif (!isSingleEnglishWord(text)) return ''; // skip fetch entirely for invalid input\nif (!navigator.onLine) return '';","typeGuard":"function isFetchResponse(res) {\n  return res && typeof res.ok === 'boolean' && typeof res.status === 'number';\n}","tryCatchPattern":"try {\n  const result = await cambridgeTranslate(text, from, to);\n} catch (e) {\n  if (String(e.message).startsWith('Http Request Error')) {\n    // network/HTTP failure: fall back to another service or show retry UI\n  } else {\n    throw e;\n  }\n}","preventionTips":["Check online status before triggering dictionary lookups","Send a browser-like User-Agent to avoid Cambridge bot detection","Debounce/throttle repeated lookups to avoid 429 rate limits","Configure a fallback translation service for HTTP failures"],"tags":["network","http","scraping","cambridge-dictionary"],"backgroundTag":"http-non-2xx-response","analyzedSha":"594d32ede96acd106b0256deaa8bb440ffcdff40","analyzedAt":"2026-09-02T18:12:21.811Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T21:17:11.164Z"}