{"record":{"id":"2838ef997daa55c8","repo":"gildas-lormeau/SingleFile","slug":"response-response-error-response-error-tostr","errorCode":null,"errorMessage":"response && response.error && response.error.toString()","messagePattern":"response && response\\.error && response\\.error\\.toString\\(\\)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/lib/single-file/fetch/content/content-fetch.js","lineNumber":183,"sourceCode":"\t\tconst promise = new Promise((resolve, reject) => pendingResponses.set(requestId, { resolve, reject }));\n\t\tawait sendMessage({ method: \"singlefile.fetch\", url, requestId, referrer: options.referrer, headers: options.headers });\n\t\treturn promise;\n\t}\n}\n\nasync function frameFetch(url, options) {\n\tconst response = await sendMessage({ method: \"singlefile.fetchFrame\", url, frameId: options.frameId, referrer: options.referrer, headers: options.headers });\n\treturn {\n\t\tstatus: response.status,\n\t\theaders: new Map(response.headers),\n\t\tarrayBuffer: async () => new Uint8Array(response.array).buffer\n\t};\n}\n\nasync function sendMessage(message) {\n\tconst response = await browser.runtime.sendMessage(message);\n\tif (!response || response.error) {\n\t\tthrow new Error(response && response.error && response.error.toString());\n\t} else {\n\t\treturn response;\n\t}\n}","sourceCodeStart":165,"sourceCodeEnd":187,"githubUrl":"https://github.com/gildas-lormeau/SingleFile/blob/517fb7c5cf2096d89933b747e862d8ecf616a9f9/src/lib/single-file/fetch/content/content-fetch.js#L165-L187","documentation":"sendMessage() wraps browser.runtime.sendMessage for SingleFile's content fetch: if the background returns no response or a response with an .error field, it throws an Error whose message is the stringified response.error. This is the transport wrapper that converts background-side failures into exceptions in the content script.","triggerScenarios":"The background page/service worker throws while handling the fetch message and replies {error: ...}; the runtime returns undefined because no listener responded or the extension context was invalidated (update/reload).","commonSituations":"Extension background crashed or was reloaded mid-session (orphaned content script); background handler itself hit a network error and forwarded it via response.error; message sent before the background listener finished registering; MV3 service worker suspended.","solutions":["Read the stringified response.error in the thrown message — it is the background's original failure; fix that root cause","Reload the page/tab to re-establish a valid browser.runtime channel after extension updates","Ensure a runtime.onMessage listener always replies (or return true for async) so responses are never undefined","Keep the MV3 service worker alive / retry the message with backoff when the response is undefined (worker wakeup race)"],"exampleFix":"// before\nconst response = await browser.runtime.sendMessage(message);\nif (!response || response.error) {\n  throw new Error(response && response.error && response.error.toString());\n}\n// after\nconst response = await browser.runtime.sendMessage(message);\nif (!response) throw new Error(\"No response from extension background (context invalidated?)\");\nif (response.error) throw new Error(`Background error: ${response.error}`);","handlingStrategy":"try-catch","validationCode":"if (typeof browser === \"undefined\" || !browser.runtime?.id) {\n  throw new Error(\"Extension context invalidated — reload the page before messaging\");\n}","typeGuard":"function isValidResponse(res) {\n  return res !== null && typeof res === \"object\" && !(\"error\" in res);\n}","tryCatchPattern":"try {\n  const resource = await fetch(url, options);\n} catch (e) {\n  if (/No response|Extension context invalidated/i.test(e.message)) {\n    await delay(500); // MV3 worker wakeup\n    resource = await fetch(url, options); // retry once\n  } else if (/Background error/i.test(e.message)) {\n    console.error(\"Background failed:\", e.message);\n  } else throw e;\n}","preventionTips":["Always reply from runtime.onMessage listeners (return true for async)","Add a one-shot retry for undefined responses (service worker cold start)","Detect and surface extension-context-invalidation to the user with a reload prompt","Serialize response.error with context instead of bare toString()"],"tags":["singlefile","extension","messaging"],"backgroundTag":"extension-message-error","analyzedSha":"517fb7c5cf2096d89933b747e862d8ecf616a9f9","analyzedAt":"2026-09-01T10:05:25.770Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}