diff --git a/lib/types/media-types.js b/lib/types/media-types.js
--- a/lib/types/media-types.js
+++ b/lib/types/media-types.js
@@ -124,7 +124,7 @@
   +step: 'video_generate_thumbnail',
   +success: boolean,
   +time: number, // ms
-  +returnCode: number,
+  +exceptionMessage: ?string,
   +thumbnailURI: string,
 };
 
diff --git a/native/media/ffmpeg.js b/native/media/ffmpeg.js
--- a/native/media/ffmpeg.js
+++ b/native/media/ffmpeg.js
@@ -4,7 +4,11 @@
 
 import type { FFmpegStatistics, VideoInfo } from 'lib/types/media-types.js';
 
-import { getVideoInfo, hasMultipleFrames } from '../utils/media-module.js';
+import {
+  getVideoInfo,
+  hasMultipleFrames,
+  generateThumbnail,
+} from '../utils/media-module.js';
 
 const maxSimultaneousCalls = {
   process: 1,
@@ -106,22 +110,11 @@
     return this.queueCommand('process', wrappedCommand);
   }
 
-  generateThumbnail(videoPath: string, outputPath: string): Promise<number> {
-    const wrappedCommand = () =>
-      FFmpeg.innerGenerateThumbnail(videoPath, outputPath);
+  generateThumbnail(videoPath: string, outputPath: string): Promise<void> {
+    const wrappedCommand = () => generateThumbnail(videoPath, outputPath);
     return this.queueCommand('process', wrappedCommand);
   }
 
-  static async innerGenerateThumbnail(
-    videoPath: string,
-    outputPath: string,
-  ): Promise<number> {
-    const thumbnailCommand = `-i ${videoPath} -frames 1 -f mjpeg ${outputPath}`;
-    const session = await FFmpegKit.execute(thumbnailCommand);
-    const returnCode = await session.getReturnCode();
-    return returnCode.getValue();
-  }
-
   getVideoInfo(path: string): Promise<VideoInfo> {
     const wrappedCommand = () => FFmpeg.innerGetVideoInfo(path);
     return this.queueCommand('probe', wrappedCommand);
diff --git a/native/media/video-utils.js b/native/media/video-utils.js
--- a/native/media/video-utils.js
+++ b/native/media/video-utils.js
@@ -195,16 +195,17 @@
   thumbnailPath: string,
 ): Promise<VideoGenerateThumbnailMediaMissionStep> {
   const thumbnailStart = Date.now();
-  const thumbnailReturnCode = await ffmpeg.generateThumbnail(
-    path,
-    thumbnailPath,
-  );
-  const thumbnailGenerationSuccessful = thumbnailReturnCode === 0;
+  let exceptionMessage;
+  try {
+    await ffmpeg.generateThumbnail(path, thumbnailPath);
+  } catch (e) {
+    exceptionMessage = getMessageForException(e);
+  }
   return {
     step: 'video_generate_thumbnail',
-    success: thumbnailGenerationSuccessful,
+    success: !exceptionMessage,
     time: Date.now() - thumbnailStart,
-    returnCode: thumbnailReturnCode,
+    exceptionMessage,
     thumbnailURI: thumbnailPath,
   };
 }
diff --git a/native/utils/media-module.js b/native/utils/media-module.js
--- a/native/utils/media-module.js
+++ b/native/utils/media-module.js
@@ -13,6 +13,7 @@
 const MediaModule: {
   +getVideoInfo: (path: string) => Promise<VideoInfo>,
   +hasMultipleFrames: (path: string) => Promise<boolean>,
+  +generateThumbnail: (inputPath: string, outputPath: string) => Promise<void>,
 } = requireNativeModule('MediaModule');
 
 export function getVideoInfo(path: string): Promise<VideoInfo> {
@@ -22,3 +23,10 @@
 export function hasMultipleFrames(path: string): Promise<boolean> {
   return MediaModule.hasMultipleFrames(path);
 }
+
+export function generateThumbnail(
+  inputPath: string,
+  outputPath: string,
+): Promise<void> {
+  return MediaModule.generateThumbnail(inputPath, outputPath);
+}