{"record":{"id":"6d4399ef0bc853e8","repo":"alyssaxuu/screenity","slug":"uploader-in-error-state-this-error","errorCode":null,"errorMessage":"Uploader in error state: ${this.error}","messagePattern":"Uploader in error state: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/pages/CloudRecorder/bunnyTusUploader.js","lineNumber":1276,"sourceCode":"        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;\n    }\n    this.lastChunkQueuedAt = Date.now();\n    this.scheduleJournalPersist();\n","sourceCodeStart":1258,"sourceCodeEnd":1294,"githubUrl":"https://github.com/alyssaxuu/screenity/blob/512606387b8d07dda5e63bb428bd063f0a2a3ed0/src/pages/CloudRecorder/bunnyTusUploader.js#L1258-L1294","documentation":"Once write() has failed and set status to 'error', all subsequent writes are rejected with this message carrying the stored this.error reason. It prevents continuing to PATCH chunks on a broken session.","triggerScenarios":"Calling write() after a previous write/PATCH failed (network error, auth expiry, untrusted location, etc.) which put the uploader into status 'error'.","commonSituations":"Retrying writes after a failed chunk without calling a reset/retry path; ignoring a rejected write promise earlier in the stream and continuing to feed chunks.","solutions":["Inspect this.error / the 'Uploader in error state' suffix to find the root cause and fix that first","Use the uploader's retry/reset mechanism (or create a new session) before resuming writes","Stop the feeding pipeline (recorder) when a write rejects instead of continuing to call write","Add a status check in callers before each write"],"exampleFix":"// before\nfor (const chunk of chunks) await uploader.write(chunk);\n// after\nfor (const chunk of chunks) {\n  if (uploader.status === \"error\") { await uploader.retry(); }\n  await uploader.write(chunk);\n}","handlingStrategy":"validation","validationCode":"if (uploader.status === \"error\") {\n  await uploader.retryOrRecreate(); // reset before more writes\n}","typeGuard":"function canWrite(uploader) { return uploader.status !== \"error\" && !!uploader.uploadUrl; }","tryCatchPattern":"try {\n  await uploader.write(chunk);\n} catch (e) {\n  if (String(e.message).startsWith(\"Uploader in error state\")) {\n    console.error(\"root cause:\", e.message); // suffix names the original error\n    stopRecorderFeed(); // stop pushing chunks on a broken session\n  }\n}","preventionTips":["Treat the first write rejection as terminal for the pipeline","Read this.error to diagnose the underlying cause","Recreate or reset the uploader rather than retrying blind writes"],"tags":["upload","tus","state-machine","error-handling"],"backgroundTag":"uploader-error-state","analyzedSha":"512606387b8d07dda5e63bb428bd063f0a2a3ed0","analyzedAt":"2026-09-02T20:59:09.419Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T02:17:09.455Z"}