{"record":{"id":"dc3a728d65bec33d","repo":"naptha/tesseract.js","slug":"network-error-while-fetching-fetchurl-response","errorCode":null,"errorMessage":"Network error while fetching ${fetchUrl}. Response code: ${resp.status}","messagePattern":"Network error while fetching (.+?)\\. Response code: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/worker-script/index.js","lineNumber":143,"sourceCode":"\n        // If `langPath` if not explicitly set by the user, the jsdelivr CDN is used.\n        // Data supporting the Legacy model is only included if `lstmOnly` is not true.\n        // This saves a significant amount of data for the majority of users that use LSTM only.\n        const langPathDownload = langPath || (lstmOnly ? `https://cdn.jsdelivr.net/npm/@tesseract.js-data/${lang}/4.0.0_best_int` : `https://cdn.jsdelivr.net/npm/@tesseract.js-data/${lang}/4.0.0`);\n\n        // For Node.js, langPath may be a URL or local file path\n        // The is-url package is used to tell the difference\n        // For the browser version, langPath is assumed to be a URL\n        if (env !== 'node' || isURL(langPathDownload) || langPathDownload.startsWith('moz-extension://') || langPathDownload.startsWith('chrome-extension://') || langPathDownload.startsWith('file://')) { /** When langPathDownload is an URL */\n          path = langPathDownload.replace(/\\/$/, '');\n        }\n\n        // langPathDownload is a URL, fetch from server\n        if (path !== null) {\n          const fetchUrl = `${path}/${lang}.traineddata${gzip ? '.gz' : ''}`;\n          const resp = await (env === 'webworker' ? fetch : adapter.fetch)(fetchUrl);\n          if (!resp.ok) {\n            throw Error(`Network error while fetching ${fetchUrl}. Response code: ${resp.status}`);\n          }\n          data = new Uint8Array(await resp.arrayBuffer());\n\n        // langPathDownload is a local file, read .traineddata from local filesystem\n        // (adapter.readCache is a generic file read function in Node.js version)\n        } else {\n          data = await adapter.readCache(`${langPathDownload}/${lang}.traineddata${gzip ? '.gz' : ''}`);\n        }\n      } else {\n        data = _lang.data; // eslint-disable-line\n      }\n    }\n\n    progress += 0.5 / langsArr.length;\n    if (res) res.progress({ workerId, status: statusText, progress });\n\n    // Check for gzip magic numbers (1F and 8B in hex)\n    const isGzip = (data[0] === 31 && data[1] === 139) || (data[1] === 31 && data[0] === 139);","sourceCodeStart":125,"sourceCodeEnd":161,"githubUrl":"https://github.com/naptha/tesseract.js/blob/a1ca80d9e31c34512d0ded75ff8821ddcf3f2f91/src/worker-script/index.js#L125-L161","documentation":"After a cache miss, loadLanguage builds fetchUrl as `${langPath}/${lang}.traineddata${gzip ? '.gz' : ''}` (defaulting langPath to the jsdelivr CDN) and fetches it. If the response is not ok (HTTP non-2xx), it throws with the status code. This reject propagates up through loadLanguage/initialize and rejects the createWorker or reinitialize promise.","triggerScenarios":"Wrong language code (e.g. 'en' instead of 'eng') returning 404; offline or DNS failure returning 5xx/0; custom langPath pointing to a misconfigured server; CORS blocking in the browser producing status 0; corporate firewall or CDN rate-limiting.","commonSituations":"Typo in the lang code; air-gapped deployment with no CDN access; self-hosted mirror with wrong path; browser extension blocking jsdelivr; region where the CDN is blocked.","solutions":["Verify the language code matches the @tesseract.js-data package name (e.g. 'eng', 'fra', 'chi_sim').","For offline/air-gapped use, pass langs as objects with embedded data: [{ code: 'eng', data: Uint8Array }], or set langPath to a reachable server/local path.","Check the fetchUrl printed in the error in a browser/curl to confirm the server and CORS headers.","Retry transient CDN failures via cacheMethod: 'write' so a later successful download persists."],"exampleFix":"// before\nconst worker = await createWorker('en'); // wrong code -> 404\n\n// after\nconst worker = await createWorker('eng'); // correct ISO 639-3 code\n\n// offline bundle\nconst eng = fs.readFileSync('./eng.traineddata');\nconst worker = await createWorker([{ code: 'eng', data: eng }]);","handlingStrategy":"retry","validationCode":"// Validate the language code before creating the worker.\nconst VALID_LANGS = new Set(['eng', 'fra', 'deu', 'spa', 'chi_sim', 'chi_tra', 'jpn', 'kor']);\nfunction assertLangs(langs) {\n  const arr = typeof langs === 'string' ? langs.split('+') : langs.map((l) => (typeof l === 'string' ? l : l.code));\n  const bad = arr.filter((l) => !VALID_LANGS.has(l));\n  if (bad.length) throw new Error('Unknown language code(s): ' + bad.join(','));\n}\nassertLangs('eng+fra');\n\n// For offline use, embed the data so no fetch happens:\nconst engData = fs.readFileSync('./traineddata/eng.traineddata');\nconst worker = await createWorker([{ code: 'eng', data: engData }]);","typeGuard":"const isLangObject = (l) =>\n  typeof l === 'object' && l !== null && typeof l.code === 'string' && (l.data instanceof Uint8Array);","tryCatchPattern":"async function createWorkerWithRetry(langs, opts, retries = 2) {\n  for (let attempt = 0; ; attempt++) {\n    try {\n      return await createWorker(langs, OEM.LSTM_ONLY, opts);\n    } catch (e) {\n      if (/Network error while fetching/.test(e.message) && attempt < retries) {\n        await new Promise((r) => setTimeout(r, 500 * (attempt + 1)));\n        continue;\n      }\n      throw e;\n    }\n  }\n}","preventionTips":["Use ISO 639-3 codes ('eng', not 'en'); verify the code exists under @tesseract.js-data on npm/jsdelivr.","Bundle traineddata as embedded data for offline or unreliable-network deployments.","Point langPath at a self-hosted mirror you control when the jsdelivr CDN is unavailable.","Set cacheMethod: 'write' so a single successful download survives transient CDN outages."],"tags":["network","language-data","fetch","cdn","offline"],"backgroundTag":null,"analyzedSha":"a1ca80d9e31c34512d0ded75ff8821ddcf3f2f91","analyzedAt":"2026-08-13T04:28:13.744Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}