{"record":{"id":"02bb15601a6edef2","repo":"transloadit/uppy","slug":"file-data-is-empty-02bb15","errorCode":null,"errorMessage":"File data is empty","messagePattern":"File data is empty","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/@uppy/webcam/src/Webcam.tsx","lineNumber":595,"sourceCode":"\n  async takeSnapshot(): Promise<void> {\n    if (this.captureInProgress) return\n\n    this.captureInProgress = true\n\n    try {\n      await this.opts.onBeforeSnapshot()\n    } catch (err) {\n      const message = typeof err === 'object' ? err.message : err\n      this.uppy.info(message, 'error', 5000)\n      throw new Error(`onBeforeSnapshot: ${message}`)\n    }\n\n    try {\n      const file = await this.getImage()\n      this.capturedMediaFile = file\n\n      if (file.data == null) throw new Error('File data is empty')\n      // Create object URL for preview\n      const capturedSnapshotUrl = URL.createObjectURL(file.data)\n      this.setPluginState({ capturedSnapshot: capturedSnapshotUrl })\n      this.captureInProgress = false\n    } catch (error) {\n      // Logging the error, except restrictions, which is handled in Core\n      this.captureInProgress = false\n      if (!error.isRestriction) {\n        this.uppy.log(error)\n      }\n    }\n  }\n\n  async getImage(): Promise<\n    Pick<LocalUppyFileNonGhost<M, B>, 'data' | 'name'>\n  > {\n    const video = this.getVideoElement()\n    if (!video) {","sourceCodeStart":577,"sourceCodeEnd":613,"githubUrl":"https://github.com/transloadit/uppy/blob/5d4dedd02a1ac0ae022c75c54aca76558f88e256/packages/@uppy/webcam/src/Webcam.tsx#L577-L613","documentation":"After Webcam's getImage() produces a Blob, takeSnapshot verifies that file.data is non-null and throws 'File data is empty' if the captured blob is missing. This indicates the underlying canvas/blob capture produced nothing.","triggerScenarios":"getImage() resolving with a file whose data is null/undefined — e.g. canvas.toBlob callback never fired, video track stopped mid-capture, or zero-dimension canvas producing no blob.","commonSituations":"Camera track ended (user/OS revoked permission) right at snapshot time, snapshot taken before the video has frames, or browser quirks where toBlob yields null (e.g. tainted/zero-size canvas).","solutions":["Ensure the webcam stream is live and the video has rendered frames before enabling the snapshot button","Re-acquire the camera stream if the track ended, then retry the snapshot","Await video.play()/loadedmetadata before capturing so videoWidth/videoHeight are non-zero"],"exampleFix":"// before\nonClick={() => webcam.getSnapshotButtonProps().onClick()}\n\n// after\nconst state = webcam.getPluginState()\nif (state.cameraReady && !state.capturedMediaFile) {\n  webcam.getSnapshotButtonProps().onClick()\n}","handlingStrategy":"validation","validationCode":"const track = stream.getVideoTracks()[0]\nif (track?.readyState === 'live' && videoRef.videoWidth > 0) {\n  webcam.getSnapshotButtonProps().onClick()\n}","typeGuard":"const isLiveCamera = (s: MediaStream | null): boolean =>\n  !!s && s.getVideoTracks().some((t) => t.readyState === 'live')","tryCatchPattern":"try { await webcam.takeSnapshot() } catch (e) { if (e.message === 'File data is empty') uppy.info('Camera not ready, try again', 'error', 3000) }","preventionTips":["Only enable the snapshot button once the camera preview shows frames","Listen for track 'ended' events to disable capture UI","Retry once after the video warms up"],"tags":["webcam","snapshot","blob","getusermedia"],"backgroundTag":"empty-capture-blob","analyzedSha":"5d4dedd02a1ac0ae022c75c54aca76558f88e256","analyzedAt":"2026-08-28T12:18:41.267Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}