diff --git a/docs/api/utility-process.md b/docs/api/utility-process.md
index 0b500b58fa9f..658c0c8804fb 100644
--- a/docs/api/utility-process.md
+++ b/docs/api/utility-process.md
@@ -44,6 +44,8 @@ Process: [Main](../glossary.md#main-process)
Returns [`UtilityProcess`](utility-process.md#class-utilityprocess)
+**Note:** `utilityProcess.fork` can only be called after the `ready` event has been emitted on `App`.
+
## Class: UtilityProcess
> Instances of the `UtilityProcess` represent the Chromium spawned child process
diff --git a/shell/browser/api/electron_api_utility_process.cc b/shell/browser/api/electron_api_utility_process.cc
index 387b82c92fe6..573d38448e16 100644
--- a/shell/browser/api/electron_api_utility_process.cc
+++ b/shell/browser/api/electron_api_utility_process.cc
@@ -21,11 +21,13 @@
#include "gin/object_template_builder.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "shell/browser/api/message_port.h"
+#include "shell/browser/browser.h"
#include "shell/browser/javascript_environment.h"
#include "shell/browser/net/system_network_context_manager.h"
#include "shell/common/gin_converters/callback_converter.h"
#include "shell/common/gin_converters/file_path_converter.h"
#include "shell/common/gin_helper/dictionary.h"
+#include "shell/common/gin_helper/error_thrower.h"
#include "shell/common/gin_helper/object_template_builder.h"
#include "shell/common/node_includes.h"
#include "shell/common/v8_util.h"
@@ -412,6 +414,13 @@ raw_ptr UtilityProcessWrapper::FromProcessId(
// static
gin::Handle UtilityProcessWrapper::Create(
gin::Arguments* args) {
+ if (!Browser::Get()->is_ready()) {
+ gin_helper::ErrorThrower(args->isolate())
+ .ThrowTypeError(
+ "utilityProcess cannot be created before app is ready.");
+ return {};
+ }
+
gin_helper::Dictionary dict;
if (!args->GetNext(&dict)) {
args->ThrowTypeError("Options must be an object.");
diff --git a/spec/fixtures/crash-cases/utility-process-app-ready/index.js b/spec/fixtures/crash-cases/utility-process-app-ready/index.js
new file mode 100644
index 000000000000..590195c83331
--- /dev/null
+++ b/spec/fixtures/crash-cases/utility-process-app-ready/index.js
@@ -0,0 +1,31 @@
+const { app, BrowserWindow, utilityProcess } = require('electron');
+
+const path = require('node:path');
+
+function createWindow () {
+ const mainWindow = new BrowserWindow();
+ mainWindow.loadFile('about:blank');
+}
+
+app.whenReady().then(() => {
+ createWindow();
+
+ app.on('activate', function () {
+ if (BrowserWindow.getAllWindows().length === 0) createWindow();
+ });
+});
+
+app.on('window-all-closed', function () {
+ if (process.platform !== 'darwin') app.quit();
+});
+
+try {
+ utilityProcess.fork(path.join(__dirname, 'utility.js'));
+} catch (e) {
+ if (/utilityProcess cannot be created before app is ready/.test(e.message)) {
+ app.exit(0);
+ } else {
+ console.error(e);
+ app.exit(1);
+ }
+}