{"record":{"id":"650051cddb28c28f","repo":"gildas-lormeau/SingleFile","slug":"err-host-fetch","errorCode":"ERR_HOST_FETCH","errorMessage":"Host fetch error (SingleFile)","messagePattern":"Host fetch error \\(SingleFile\\)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/lib/single-file/fetch/content/content-fetch.js","lineNumber":124,"sourceCode":"\t\t\t\t\t\tdocument.removeEventListener(FETCH_RESPONSE_EVENT, onResponseFetch, false);\n\t\t\t\t\t\tif (event.detail.response) {\n\t\t\t\t\t\t\tresolve({\n\t\t\t\t\t\t\t\tstatus: event.detail.status,\n\t\t\t\t\t\t\t\theaders: new Map(event.detail.headers),\n\t\t\t\t\t\t\t\tarrayBuffer: async () => event.detail.response\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\treject(event.detail.error);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\treject();\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t\treturn result;\n\t} else {\n\t\tthrow new Error(ERR_HOST_FETCH);\n\t}\n}\n\nexport {\n\tfetchResource as fetch,\n\tframeFetch\n};\n\nasync function fetchResource(url, options = {}, useHostFetch = true) {\n\ttry {\n\t\tconst fetchOptions = {\n\t\t\tcache: options.cache || \"force-cache\",\n\t\t\theaders: options.headers,\n\t\t\treferrerPolicy: options.referrerPolicy || \"strict-origin-when-cross-origin\"\n\t\t};\n\t\tlet response;\n\t\ttry {\n\t\t\tif ((options.referrer && !USE_HOST_FETCH) || !useHostFetch) {","sourceCodeStart":106,"sourceCodeEnd":142,"githubUrl":"https://github.com/gildas-lormeau/SingleFile/blob/517fb7c5cf2096d89933b747e862d8ecf616a9f9/src/lib/single-file/fetch/content/content-fetch.js#L106-L142","documentation":"hostFetch() in SingleFile's content-fetch only works when running with a host/extension bridge available; when the environment can't provide it (the else branch), it throws ERR_HOST_FETCH with the message \"Host fetch error (SingleFile)\". Callers like fetchResource receive this when the privileged fetch channel is absent.","triggerScenarios":"fetchResource calls hostFetch while the extension runtime/handler is unavailable: content script running without the background listener registered, extension context invalidated after an update/reload, or the library used outside the extension host context.","commonSituations":"Extension was auto-updated while a tab's content script was still alive (orphaned context); SingleFile used in a page/embedded context where browser.runtime messaging is unavailable; background service worker asleep or crashed in Manifest V3.","solutions":["Reload the tab (re-injects the content script) so it reconnects to the refreshed extension background context","Ensure the background/service-worker listener for the fetch message is registered and alive before fetchResource runs","Wrap hostFetch calls so the error propagates with ERR_HOST_FETCH and fall back to an in-page fetch where the host bridge is optional","Update SingleFile to the latest version if extension updates repeatedly orphan contexts"],"exampleFix":"// before\nconst result = await hostFetch(url, options);\n// after\nlet result;\ntry {\n  result = await hostFetch(url, options);\n} catch (e) {\n  if (String(e.message).includes(ERR_HOST_FETCH)) result = await fallbackFetch(url, options);\n  else throw e;\n}","handlingStrategy":"fallback","validationCode":"const hostAvailable = typeof browser !== \"undefined\" && browser.runtime && browser.runtime.id;\nif (!hostAvailable) throw new Error(\"SingleFile host context unavailable; use in-page fetch\");","typeGuard":"function canHostFetch() {\n  try { return typeof browser !== \"undefined\" && !!browser.runtime?.id && typeof browser.runtime.sendMessage === \"function\"; }\n  catch { return false; }\n}","tryCatchPattern":"try {\n  const resource = await fetch(url, options);\n} catch (e) {\n  if (String(e.message).includes(\"Host fetch error\") || e.message === \"ERR_HOST_FETCH\") {\n    resource = await plainFetch(url, options); // in-page fallback\n  } else throw e;\n}","preventionTips":["Detect orphaned extension contexts (browser.runtime.id undefined) and prompt a tab reload","Register background fetch listeners synchronously at service-worker startup","Keep a plain-fetch fallback path for non-extension environments","Re-inject content scripts after extension updates"],"tags":["singlefile","extension","fetch"],"backgroundTag":"host-fetch-unavailable","analyzedSha":"517fb7c5cf2096d89933b747e862d8ecf616a9f9","analyzedAt":"2026-09-01T10:05:25.770Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}