{"record":{"id":"1413c5c1384fea7c","repo":"alyssaxuu/screenity","slug":"invalid-tus-location-err-message-err","errorCode":null,"errorMessage":"Invalid TUS location: ${err?.message || err}","messagePattern":"Invalid TUS location: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/pages/CloudRecorder/bunnyTusUploader.js","lineNumber":1228,"sourceCode":"        )}`,\n      },\n    });\n\n    if (!res.ok) throw new Error(\"Failed to start TUS upload session\");\n    const location = res.headers.get(\"location\");\n    const resolved = location.startsWith(\"/\")\n      ? `https://video.bunnycdn.com${location}`\n      : location;\n    // Defense-in-depth: TUS Location header must stay on Bunny's host. Without\n    // this, a redirect to attacker.com would receive subsequent PATCHes\n    // carrying recording chunks plus the AuthorizationSignature header.\n    try {\n      const parsed = new URL(resolved);\n      if (parsed.host !== \"video.bunnycdn.com\") {\n        throw new Error(`Untrusted TUS location host: ${parsed.host}`);\n      }\n    } catch (err) {\n      throw new Error(`Invalid TUS location: ${err?.message || err}`);\n    }\n    this.uploadUrl = resolved;\n\n    // Persist BEFORE save-upload-meta: the local journal is the only recovery\n    // path if the extension crashes before the backend records the URL.\n    await this.persistUploadJournal({ force: true });\n\n    if (this.userToken) {\n      fetch(`${API_BASE}/bunny/videos/save-upload-meta`, {\n        method: \"POST\",\n        headers: {\n          \"Content-Type\": \"application/json\",\n          Authorization: `Bearer ${this.userToken}`,\n        },\n        body: JSON.stringify({\n          mediaId: this.mediaId,\n          uploadUrl: this.uploadUrl,\n          signature: this.signature,","sourceCodeStart":1210,"sourceCodeEnd":1246,"githubUrl":"https://github.com/alyssaxuu/screenity/blob/512606387b8d07dda5e63bb428bd063f0a2a3ed0/src/pages/CloudRecorder/bunnyTusUploader.js#L1210-L1246","documentation":"Thrown when the resolved TUS Location string cannot be parsed as a URL at all (new URL() threw) — the catch block rewraps any failure of the parsing/validation step, including the untrusted-host error from inside the try, into 'Invalid TUS location: ...'.","triggerScenarios":"Location header missing, empty, or containing characters invalid for a URL so new URL() throws; also triggered by the inner untrusted-host throw being caught by this same try block and rewrapped.","commonSituations":"Proxy stripping the Location header so resolved is null/undefined; Bunny returning a relative path handled incorrectly; URL containing unencoded spaces or control characters.","solutions":["Log the raw Location header value to see what was received","Handle a null/missing Location header before constructing the URL and give a distinct error","Verify no proxy or extension strips or mangles response headers","Note that the untrusted-host error is rewrapped here — check the message suffix to distinguish the real cause"],"exampleFix":"// before\n} catch (err) {\n  throw new Error(`Invalid TUS location: ${err?.message || err}`);\n}\n// after\n} catch (err) {\n  if (err instanceof Error && err.message.startsWith(\"Untrusted TUS location\")) throw err;\n  if (!location) throw new Error(\"TUS creation response missing Location header\");\n  throw new Error(`Invalid TUS location: ${err?.message || err}`);\n}","handlingStrategy":"validation","validationCode":"if (!location) throw new Error(\"TUS create response missing Location header\");\nlet parsed;\ntry { parsed = new URL(resolved); } catch { throw new Error(\"malformed TUS location\"); }","typeGuard":"function isValidUrl(s) { try { new URL(s); return true; } catch { return false; } }","tryCatchPattern":"try {\n  await uploader.init();\n} catch (e) {\n  if (String(e.message).startsWith(\"Invalid TUS location\")) {\n    console.warn(\"Location header issue:\", e.message); // includes rewrapped causes\n  }\n}","preventionTips":["Check the Location header exists before parsing","Distinguish host-mismatch from parse failure in your own validation","Test through any corporate proxy that may mangle headers"],"tags":["url-parsing","upload","tus","http"],"backgroundTag":"invalid-upload-location-url","analyzedSha":"512606387b8d07dda5e63bb428bd063f0a2a3ed0","analyzedAt":"2026-09-02T20:59:09.419Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T02:17:09.455Z"}