alyssaxuu/screenity · error · Error

Camera track has ended

Error message

Camera track has ended

What it means

After setting up the camera uploader, CloudRecorder grabs the first video track from the stored camera MediaStream and throws if its readyState is already 'ended'. A video track ends when its source device is disconnected, revoked, or stopped, so recording cannot proceed. This guard prevents starting an encoder against a dead track.

Source

Thrown at src/pages/CloudRecorder/CloudRecorder.jsx:4234

              camera: offset,
              ts: now,
            };
            patchTrackState("camera", {
              lastUploadOffset: offset,
              uploaderUpdatedAt: now,
            });
            if (now - (lastUploadProgress.current.lastPersistAt || 0) > 2000) {
              lastUploadProgress.current.lastPersistAt = now;
              persistSessionState();
            }
          },
          onStall: onStall("camera"),
          onTelemetry: onUploaderTelemetry("camera"),
          onStateChange: onUploaderStateChange("camera"),
        });
        const track = cameraStream.current.getVideoTracks()[0];
        if (track?.readyState === "ended") {
          throw new Error("Camera track has ended");
        }
        let { width, height } = track.getSettings();
        if (encoderKinds.camera === "webcodecs") {
          const downscaled = computeEncodedDimensions({ width, height });
          if (downscaled.width > 0 && downscaled.height > 0) {
            width = downscaled.width;
            height = downscaled.height;
          }
        }
        // Omit linkedMediaId; server groups partners by shared sceneId
        // in usedIn now. Lifts the serial wait on screen's mediaId
        // (~3s dev, 500ms-1s prod).
        cameraInitOpts = {
          title: "Camera Recording",
          type: "camera",
          linkedMediaId: null,
          width,
          height,

View on GitHub (pinned to 512606387b)

Solutions

  1. Retry getUserMedia to obtain a fresh camera stream, then rebuild the uploader with the new track.
  2. Listen for track 'ended' events on cameraStream.current and prompt the user to reconnect/select a camera before starting the recording.
  3. Check navigator.mediaDevices.enumerateDevices() for an available videoinput and guide the user to reselect it in device settings.
  4. Stop and clean up the current recorder session (cancel encoders/uploads) so a stale stream is not reused on retry.
  5. Avoid calling track.stop() on the camera stream anywhere before recording starts; audit shared references to the stream.

Example fix

// before
const track = cameraStream.current.getVideoTracks()[0];
if (track?.readyState === "ended") {
  throw new Error("Camera track has ended");
}
// after
let track = cameraStream.current.getVideoTracks()[0];
if (!track || track.readyState === "ended") {
  cameraStream.current = await navigator.mediaDevices.getUserMedia({ video: true });
  track = cameraStream.current.getVideoTracks()[0];
}
Defensive patterns

Strategy: type-guard

Validate before calling

const track = cameraStream.current?.getVideoTracks()[0];
if (!track || track.readyState !== "live") {
  cameraStream.current = await navigator.mediaDevices.getUserMedia({ video: true });
}

Type guard

function hasLiveCameraTrack(stream) {
  const track = stream?.getVideoTracks()[0];
  return !!track && track.readyState === "live";
}

Try / catch

try {
  startCameraUploader();
} catch (err) {
  if (err.message === "Camera track has ended") {
    await reacquireCameraStream();
    startCameraUploader();
  } else {
    throw err;
  }
}

Prevention

When it happens

Trigger: The webcam is unplugged or the USB hub drops between getUserMedia and uploader start; the user revokes camera permission via the browser's site controls; another application or code path calls track.stop() on the camera stream before this point.

Common situations: Laptop dock/undock during recording setup; user switches cameras in OS settings mid-flow; camera used exclusively by another app (Zoom/Teams) causing device release; long stalls before start where the OS turned the camera off.

Related errors


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