{"record":{"id":"979ce2756d40d4ad","repo":"alyssaxuu/screenity","slug":"uploader-has-already-been-initialized","errorCode":null,"errorMessage":"Uploader has already been initialized","messagePattern":"Uploader has already been initialized","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/pages/CloudRecorder/bunnyTusUploader.js","lineNumber":825,"sourceCode":"      });\n      return null;\n    }\n  }\n  async initialize(\n    projectId,\n    {\n      title,\n      type,\n      width = null,\n      height = null,\n      linkedMediaId = null,\n      reuse = null,\n      sceneId = null,\n      sessionId = null,\n    },\n  ) {\n    if (this.status !== \"idle\" && this.status !== \"error\") {\n      throw new Error(\"Uploader has already been initialized\");\n    }\n\n    // Fire-and-forget orphan-journal cleanup; doesn't block the hot path.\n    void sweepStaleUploadJournals();\n\n    try {\n      this.projectId = projectId;\n      this.metadata = { title, type, linkedMediaId, sceneId };\n      this.trackType = this.trackType || type || null;\n      this.sceneId = sceneId;\n      this.metaWidth = width;\n      this.metaHeight = height;\n      this.sessionId = sessionId || this.sessionId || null;\n      this.journalLookupKey = this.getJournalLookupKey(projectId, sceneId, type);\n      this.createdAt = this.createdAt || Date.now();\n\n      this.status = \"initializing\";\n      this.error = null;","sourceCodeStart":807,"sourceCodeEnd":843,"githubUrl":"https://github.com/alyssaxuu/screenity/blob/512606387b8d07dda5e63bb428bd063f0a2a3ed0/src/pages/CloudRecorder/bunnyTusUploader.js#L807-L843","documentation":"BunnyTusUploader.initialize() enforces a single lifecycle: it may only be called while status is 'idle' or 'error'. Calling it on an uploader already 'initializing', 'ready', or actively uploading throws this error to prevent clobbering an in-flight or completed tus upload session (videoId, uploadUrl, offset state).","triggerScenarios":"resumeOneJournal calls initialize() on a reused uploader instance whose status is not 'idle'/'error' — e.g. double resume after an error-free upload, re-initializing the same screenUploader/cameraUploader instance for a second scene, or concurrent resume journal entries targeting the same uploader.","commonSituations":"Recording restart flows that reuse singleton uploader refs without resetting status, multi-scene pipelines re-invoking initialize() on the same instance, race between two resumeOneJournal calls, or after a successful upload where status is 'complete' but code assumes it can re-init.","solutions":["Create a fresh BunnyTusUploader instance per upload/scene instead of reusing the singleton","Reset the uploader before re-initializing (add a reset()/dispose() that sets status back to 'idle')","Check this.status before calling initialize and skip when it's already initialized/ready","Serialize resumeOneJournal calls so two journals can't race on the same uploader instance","If intentionally re-initializing after 'complete', gate the guard to allow that status explicitly"],"exampleFix":"// before\nawait uploader.initialize(projectId, { title, type, sceneId });\n// after\nif (uploader.status === \"idle\" || uploader.status === \"error\") {\n  await uploader.initialize(projectId, { title, type, sceneId });\n} else {\n  uploader = new BunnyTusUploader();\n  await uploader.initialize(projectId, { title, type, sceneId });\n}","handlingStrategy":"validation","validationCode":"function canInitialize(uploader) {\n  return uploader.status === \"idle\" || uploader.status === \"error\";\n}\nif (!canInitialize(uploader)) {\n  uploader = uploader.clone() ?? new BunnyTusUploader();\n}","typeGuard":"function isReinitializable(uploader) {\n  return uploader && (uploader.status === \"idle\" || uploader.status === \"error\");\n}","tryCatchPattern":"try {\n  await uploader.initialize(projectId, { title, type, sceneId });\n} catch (err) {\n  if (err.message === \"Uploader has already been initialized\") {\n    uploader = new BunnyTusUploader();\n    await uploader.initialize(projectId, { title, type, sceneId });\n  } else throw err;\n}","preventionTips":["Guard with a status check before every initialize() call","Use a new uploader instance per scene/track instead of shared singletons","Serialize resumeOneJournal invocations to avoid racing on one instance","Reset or dispose uploaders in restart flows so status returns to 'idle' before re-init"],"tags":["upload","state-machine","tus","bunny","lifecycle"],"backgroundTag":"uploader-already-initialized","analyzedSha":"512606387b8d07dda5e63bb428bd063f0a2a3ed0","analyzedAt":"2026-09-02T20:59:09.419Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T02:17:09.455Z"}