{"record":{"id":"ababfd620588c946","repo":"alyssaxuu/screenity","slug":"write-after-finalize","errorCode":"write-after-finalize","errorMessage":"Cannot write during finalization","messagePattern":"Cannot write during finalization","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/pages/CloudRecorder/bunnyTusUploader.js","lineNumber":1270,"sourceCode":"        }),\n      }).catch((err) =>\n        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);","sourceCodeStart":1252,"sourceCodeEnd":1288,"githubUrl":"https://github.com/alyssaxuu/screenity/blob/512606387b8d07dda5e63bb428bd063f0a2a3ed0/src/pages/CloudRecorder/bunnyTusUploader.js#L1252-L1288","documentation":"write() refuses chunks once the uploader has entered finalization (isFinalizing true). Any bytes arriving after finalize begins cannot be delivered, so the chunk size is recorded in bytesLostAfterFinalize, an uploader error is set, and the chunk is rejected.","triggerScenarios":"Calling uploader.write(chunk) after finalize()/stop was invoked, typically from a recording callback that is still delivering MediaRecorder/webcodecs data while the stop path is running.","commonSituations":"Race between the recorder's last dataavailable event and the stop/finalize flow; user stops the recording while a burst of chunks is queued; double-stop wiring firing finalize before the final flush.","solutions":["Stop the media recorder and wait for its final dataavailable event BEFORE calling finalize","Queue chunks and drain the queue before starting finalization (set isFinalizing only after the queue is empty)","Check uploader.isFinalizing in the write path and drop/flush chunks gracefully instead of crashing callers","Inspect bytesLostAfterFinalize to quantify how much data was dropped and adjust the stop sequence"],"exampleFix":"// before\nawait uploader.finalize();\nrecorder.stop(); // chunks still arrive after finalize\n// after\nrecorder.stop();\nawait once(recorder, \"stop\"); // flush all remaining chunks\nawait uploader.finalize();","handlingStrategy":"try-catch","validationCode":"if (uploader.isFinalizing) {\n  lostBytes += chunk.size; // park or drop before calling write\n}","typeGuard":null,"tryCatchPattern":"try {\n  await uploader.write(chunk);\n} catch (e) {\n  if (String(e.message).includes(\"Cannot write during finalization\")) {\n    // stop feeding; finalize is already in progress\n    recorderStreamClose();\n  }\n}","preventionTips":["Always stop the recorder and await its final flush before finalize","Drain queued chunks before setting isFinalizing","Track bytesLostAfterFinalize to validate the stop sequence","Avoid double-stop paths that trigger finalize early"],"tags":["upload","tus","race-condition","state-machine"],"backgroundTag":"write-after-finalize","analyzedSha":"512606387b8d07dda5e63bb428bd063f0a2a3ed0","analyzedAt":"2026-09-02T20:59:09.419Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T02:17:09.455Z"}