alyssaxuu/screenity · error · Error

Uploader has already been initialized

Error message

Uploader has already been initialized

What it means

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).

Source

Thrown at src/pages/CloudRecorder/bunnyTusUploader.js:825

      });
      return null;
    }
  }
  async initialize(
    projectId,
    {
      title,
      type,
      width = null,
      height = null,
      linkedMediaId = null,
      reuse = null,
      sceneId = null,
      sessionId = null,
    },
  ) {
    if (this.status !== "idle" && this.status !== "error") {
      throw new Error("Uploader has already been initialized");
    }

    // Fire-and-forget orphan-journal cleanup; doesn't block the hot path.
    void sweepStaleUploadJournals();

    try {
      this.projectId = projectId;
      this.metadata = { title, type, linkedMediaId, sceneId };
      this.trackType = this.trackType || type || null;
      this.sceneId = sceneId;
      this.metaWidth = width;
      this.metaHeight = height;
      this.sessionId = sessionId || this.sessionId || null;
      this.journalLookupKey = this.getJournalLookupKey(projectId, sceneId, type);
      this.createdAt = this.createdAt || Date.now();

      this.status = "initializing";
      this.error = null;

View on GitHub (pinned to 512606387b)

Solutions

  1. Create a fresh BunnyTusUploader instance per upload/scene instead of reusing the singleton
  2. Reset the uploader before re-initializing (add a reset()/dispose() that sets status back to 'idle')
  3. Check this.status before calling initialize and skip when it's already initialized/ready
  4. Serialize resumeOneJournal calls so two journals can't race on the same uploader instance
  5. If intentionally re-initializing after 'complete', gate the guard to allow that status explicitly

Example fix

// before
await uploader.initialize(projectId, { title, type, sceneId });
// after
if (uploader.status === "idle" || uploader.status === "error") {
  await uploader.initialize(projectId, { title, type, sceneId });
} else {
  uploader = new BunnyTusUploader();
  await uploader.initialize(projectId, { title, type, sceneId });
}
Defensive patterns

Strategy: validation

Validate before calling

function canInitialize(uploader) {
  return uploader.status === "idle" || uploader.status === "error";
}
if (!canInitialize(uploader)) {
  uploader = uploader.clone() ?? new BunnyTusUploader();
}

Type guard

function isReinitializable(uploader) {
  return uploader && (uploader.status === "idle" || uploader.status === "error");
}

Try / catch

try {
  await uploader.initialize(projectId, { title, type, sceneId });
} catch (err) {
  if (err.message === "Uploader has already been initialized") {
    uploader = new BunnyTusUploader();
    await uploader.initialize(projectId, { title, type, sceneId });
  } else throw err;
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of alyssaxuu/screenity@512606387b (2026-09-02). Data as JSON: /api/errors/979ce2756d40d4ad. Report an issue: GitHub.