alyssaxuu/screenity · error · Error
Failed to start TUS upload session
Error message
Failed to start TUS upload session
What it means
BunnyTusUploader creates a TUS upload session by POSTing to Bunny's video CDN creation endpoint and throws this when the HTTP response is not ok. It means Bunny rejected session creation (auth, quota, container/metadata, or network-level failure surfaced as a non-2xx), so no upload URL exists and no bytes can be sent.
Source
Thrown at src/pages/CloudRecorder/bunnyTusUploader.js:1214
}
async initTusUpload() {
const res = await fetch("https://video.bunnycdn.com/tusupload", {
method: "POST",
headers: {
"Tus-Resumable": "1.0.0",
"Upload-Defer-Length": "1",
AuthorizationSignature: this.signature,
AuthorizationExpire: String(this.expires),
LibraryId: String(this.libraryId),
VideoId: this.videoId,
"Upload-Metadata": `filetype ${btoa(this.container || "video/webm")},title ${btoa(
this.metadata.title,
)}`,
},
});
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 recoveryView on GitHub (pinned to 512606387b)
Solutions
- Log res.status and res body at the throw site to identify which 4xx/5xx Bunny returned
- Refresh the Bunny auth signature/token before creating the session and retry once
- Ensure metadata values are ASCII-safe before btoa (use a UTF-8 safe base64 encoder for the title)
- Verify the library id and create endpoint URL match your Bunny account/region
- Check Bunny status/incidents if failures are widespread
Example fix
// before
if (!res.ok) throw new Error("Failed to start TUS upload session");
// after
if (!res.ok) {
const body = await res.text().catch(() => "");
throw new Error(`Failed to start TUS upload session: HTTP ${res.status} ${body.slice(0, 200)}`);
} Defensive patterns
Strategy: try-catch
Validate before calling
// before creating a session
if (!bunnyToken) throw new Error("missing Bunny auth token");
const res = await fetch(createUrl, { method: "POST", headers });
if (!res.ok) console.error("TUS create failed", res.status, await res.text()); Try / catch
try {
await uploader.init();
} catch (e) {
if (String(e.message).includes("Failed to start TUS upload session")) {
await refreshBunnyToken();
await uploader.init(); // single retry after re-auth
} else throw e;
} Prevention
- Refresh auth signatures proactively before long recordings
- Keep metadata ASCII-safe before base64 encoding
- Log HTTP status/body from the create request
- Verify library id and endpoint URL per environment
When it happens
Trigger: POST to the TUS creation endpoint returns non-ok status: invalid or expired AuthorizationSignature/token, missing or mis-encoded Upload-Metadata (e.g. non-ASCII title that btoa cannot encode), wrong collection/container id, or Bunny outage returning 4xx/5xx.
Common situations: Expired Bunny API key or signed upload token; recording started after auth expired; btoa throwing on Unicode metadata upstream; wrong library id in the creation URL; CORS/proxy stripping the Location header in dev environments.
Related errors
- Invalid TUS location: ${err?.message || err}
- No valid media uploaded - both screen and camera mediaId are
- Failed to initialize uploaders
- Uploader has already been initialized
- resume-offset-unverified
AI-assisted analysis of alyssaxuu/screenity@512606387b (2026-09-02).
Data as JSON: /api/errors/955afb4605a001eb.
Report an issue: GitHub.