alyssaxuu/screenity · error · Error
Invalid TUS location: ${err?.message || err}
Error message
Invalid TUS location: ${err?.message || err} What it means
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: ...'.
Source
Thrown at src/pages/CloudRecorder/bunnyTusUploader.js:1228
)}`,
},
});
if (!res.ok) throw new Error("Failed to start TUS upload session");
const location = res.headers.get("location");
const resolved = location.startsWith("/")
? `https://video.bunnycdn.com${location}`
: location;
// Defense-in-depth: TUS Location header must stay on Bunny's host. Without
// this, a redirect to attacker.com would receive subsequent PATCHes
// carrying recording chunks plus the AuthorizationSignature header.
try {
const parsed = new URL(resolved);
if (parsed.host !== "video.bunnycdn.com") {
throw new Error(`Untrusted TUS location host: ${parsed.host}`);
}
} catch (err) {
throw new Error(`Invalid TUS location: ${err?.message || err}`);
}
this.uploadUrl = resolved;
// Persist BEFORE save-upload-meta: the local journal is the only recovery
// path if the extension crashes before the backend records the URL.
await this.persistUploadJournal({ force: true });
if (this.userToken) {
fetch(`${API_BASE}/bunny/videos/save-upload-meta`, {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${this.userToken}`,
},
body: JSON.stringify({
mediaId: this.mediaId,
uploadUrl: this.uploadUrl,
signature: this.signature,View on GitHub (pinned to 512606387b)
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
Example fix
// before
} catch (err) {
throw new Error(`Invalid TUS location: ${err?.message || err}`);
}
// after
} catch (err) {
if (err instanceof Error && err.message.startsWith("Untrusted TUS location")) throw err;
if (!location) throw new Error("TUS creation response missing Location header");
throw new Error(`Invalid TUS location: ${err?.message || err}`);
} Defensive patterns
Strategy: validation
Validate before calling
if (!location) throw new Error("TUS create response missing Location header");
let parsed;
try { parsed = new URL(resolved); } catch { throw new Error("malformed TUS location"); } Type guard
function isValidUrl(s) { try { new URL(s); return true; } catch { return false; } } Try / catch
try {
await uploader.init();
} catch (e) {
if (String(e.message).startsWith("Invalid TUS location")) {
console.warn("Location header issue:", e.message); // includes rewrapped causes
}
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: Proxy stripping the Location header so resolved is null/undefined; Bunny returning a relative path handled incorrectly; URL containing unencoded spaces or control characters.
Related errors
- Failed to start TUS upload session
- Uploader has already been initialized
- resume-offset-unverified
- Untrusted TUS location host: ${parsed.host}
- write-after-finalize
AI-assisted analysis of alyssaxuu/screenity@512606387b (2026-09-02).
Data as JSON: /api/errors/1413c5c1384fea7c.
Report an issue: GitHub.