{"record":{"id":"c4b1148a4f34753f","repo":"alyssaxuu/screenity","slug":"uploader-paused","errorCode":null,"errorMessage":"Uploader paused","messagePattern":"Uploader paused","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"src/pages/CloudRecorder/bunnyTusUploader.js","lineNumber":1272,"sourceCode":"        this.debugLog(\"save-upload-meta failed (non-blocking)\", { error: String(err) }),\n      );\n    } else {\n      this.debugLog(\"Skipping save-upload-meta because user token is missing\", {\n        mediaId: this.mediaId,\n        uploadUrl: this.uploadUrl,\n        signature: this.signature,\n        expires: this.expires,\n      });\n    }\n  }\n\n  async write(chunk) {\n    if (this.isFinalizing) {\n      this.bytesLostAfterFinalize += chunk?.size || 0;\n      this.setUploaderError(\"write-after-finalize\");\n      throw new Error(\"Cannot write during finalization\");\n    }\n    if (this.isPaused) throw new Error(\"Uploader paused\");\n    if (!this.uploadUrl) throw new Error(\"Uploader not initialized\");\n\n    if (this.status === \"error\") {\n      throw new Error(`Uploader in error state: ${this.error}`);\n    }\n\n    await this.checkAuthExpiration();\n    this.status = \"uploading\";\n    if (!this.hasEmittedClientStarted) {\n      this.hasEmittedClientStarted = true;\n      this.emitTelemetry(\"upload_client_started\");\n    }\n\n    for (let i = 0; i < chunk.size; i += this.CHUNK_SIZE) {\n      const subChunk = chunk.slice(i, i + this.CHUNK_SIZE);\n      this.chunkQueue.push(subChunk);\n      this.queuedBytes += subChunk.size;\n      this.totalBytes += subChunk.size;","sourceCodeStart":1254,"sourceCodeEnd":1290,"githubUrl":"https://github.com/alyssaxuu/screenity/blob/512606387b8d07dda5e63bb428bd063f0a2a3ed0/src/pages/CloudRecorder/bunnyTusUploader.js#L1254-L1290","documentation":"Guard in BunnyTusUploader.write(): a chunk arrived while this.isPaused was true, so the uploader refuses the write to preserve tus protocol ordering. The caller must resume the uploader before delivering further chunks.","triggerScenarios":"Calling write() while the user (or code) paused the uploader via pause(); typically from an active recorder dataavailable callback during a pause.","commonSituations":"User pauses recording/upload from the UI while the recorder keeps producing chunks; pause/resume state desync between recorder controls and uploader.","solutions":["Buffer or drop the chunk and resume the uploader before continuing the stream","Ensure the pause control (UI or backpressure) stops the chunk source, not just the uploader","Catch this in the writer pipeline and retry the chunk after resume"],"exampleFix":"// before\nawait uploader.write(chunk); // throws if paused\n// after\nif (uploader.isPaused) { pendingChunks.push(chunk); } else { await uploader.write(chunk); }","handlingStrategy":"try-catch","validationCode":"if (uploader.isPaused) { queue.push(chunk); return; }\nawait uploader.write(chunk);","typeGuard":null,"tryCatchPattern":"try {\n  await uploader.write(chunk);\n} catch (e) {\n  if (e.message === \"Uploader paused\") {\n    queue.push(chunk); // replay after resume()\n    uploader.once(\"resumed\", drainQueue);\n  }\n}","preventionTips":["Pause recorder and uploader together from the UI","Buffer chunks during pause instead of dropping","Keep pause/resume state in one source of truth"],"tags":["upload","tus","state-machine","pause"],"backgroundTag":"uploader-paused-write-rejected","analyzedSha":"512606387b8d07dda5e63bb428bd063f0a2a3ed0","analyzedAt":"2026-09-02T20:59:09.419Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T02:17:09.455Z"}