alyssaxuu/screenity · error · Error
resume-offset-unverified
resume-offset-unverified
Error message
Could not verify server offset during resume.
What it means
When initialize() resumes from a persisted journal with a saved uploadUrl, it queries the TUS server for the current byte offset via getServerOffset() to avoid re-uploading or corrupting data. If the response is not a finite non-negative number, the uploader cannot trust the resume position, marks the uploader error as 'resume-offset-unverified', and throws rather than guessing an offset. This is a safety guard: resuming at a wrong offset would produce a corrupted Bunny video.
Source
Thrown at src/pages/CloudRecorder/bunnyTusUploader.js:1082
}
throw refreshErr;
}
if (this.uploadUrl) {
const serverOffset = await this.getServerOffset();
if (Number.isFinite(serverOffset) && serverOffset >= 0) {
this.lastServerOffset = serverOffset;
this.offset = serverOffset;
this.totalBytes = Math.max(this.totalBytes || 0, serverOffset);
if (this.initializedFromResume || serverOffset > 0) {
this.emitTelemetry("upload_resumed", {
resumedOffset: serverOffset,
resumeCount: this.resumeCount || 1,
});
}
} else {
this.setUploaderError("resume-offset-unverified");
throw new Error("Could not verify server offset during resume.");
}
} else {
await this.initTusUpload();
}
await this.persistUploadJournal({ force: true });
this.startHeartbeat();
this.status = "ready";
this.readyAt = Date.now();
this.emitTelemetry("upload_started", {
resumed: this.initializedFromResume,
resumeCount: this.resumeCount || 0,
});
this.scheduleJournalPersist({ force: true });
return { videoId: this.videoId, mediaId: this.mediaId };
} catch (err) {
if (this.status !== "error") {
this.setUploaderError("initialize-failed", err);View on GitHub (pinned to 512606387b)
Solutions
- Clear the stale upload journal (uploader.clearUploadJournal()) and call initialize() again so it starts a fresh TUS upload instead of resuming.
- Check whether the TUS upload URL still exists (HEAD it manually); a 404 means the video was deleted and resume is impossible — create a new video.
- Inspect getServerOffset() response handling: verify the request succeeded and the Upload-Offset header is present; fix parsing if the server changed headers.
- If it was a transient network failure during the HEAD, simply retry initialize() — the journal is still intact.
- If this recurs, check tus-auth signature expiry: an expired signature can make the offset request fail; ensure refreshTusAuth() succeeds before offset verification.
Example fix
// before
await uploader.initialize({ projectId, sceneId, type });
// after
try {
await uploader.initialize({ projectId, sceneId, type });
} catch (err) {
if (err?.message?.includes("verify server offset")) {
await uploader.clearUploadJournal(); // discard untrusted resume state
await uploader.initialize({ projectId, sceneId, type }); // fresh upload
} else throw err;
} Defensive patterns
Strategy: try-catch
Validate before calling
const res = await fetch(uploadUrl, { method: 'HEAD' });
const offset = Number(res.headers.get('Upload-Offset'));
if (res.ok && Number.isFinite(offset) && offset >= 0) {
await uploader.initialize({ projectId, sceneId, type }); // safe to resume
} Type guard
function isVerifiableOffset(v) {
return typeof v === 'number' && Number.isFinite(v) && v >= 0;
} Try / catch
try {
await uploader.initialize({ projectId, sceneId, type });
} catch (err) {
if (err?.message?.includes('verify server offset') || err?.code === 'resume-offset-unverified') {
await uploader.clearUploadJournal(); // drop untrusted resume state
await uploader.initialize({ projectId, sceneId, type }); // fresh upload
} else throw err;
} Prevention
- Clear the journal when the Bunny video is known deleted (tus-auth 404) instead of retrying resume forever.
- HEAD the uploadUrl yourself before resuming a long-interrupted upload.
- Treat signature expiry: ensure tus-auth refresh succeeds before offset verification.
- Persist a last-verified timestamp with the journal and skip resume if it's too old.
- Never bypass the offset check — resuming at a wrong offset corrupts the video.
When it happens
Trigger: initialize() loaded a resume journal that had an uploadUrl, then getServerOffset() returned NaN/null/undefined or a negative value — e.g. the TUS HEAD request failed, returned an unexpected status, or the Upload-Offset header was missing/unparseable.
Common situations: The Bunny video was deleted server-side (orphan reaper / manual cleanup) so the TUS URL 404s; upload URL expired or signature invalidated between sessions; network error during the offset HEAD request; server response shape changed so the offset header isn't parsed.
Related errors
- Uploader has already been initialized
- Failed to start TUS upload session
- Untrusted TUS location host: ${parsed.host}
- Invalid TUS location: ${err?.message || err}
- write-after-finalize
AI-assisted analysis of alyssaxuu/screenity@512606387b (2026-09-02).
Data as JSON: /api/errors/6e32f2490a2bc43e.
Report an issue: GitHub.