windows環境 electron-forge で "Error: ENOENT no such file or directory, open ..." エラが出て make できない

electron-forge の Webpack + Typescript のテンプレートを利用して electron デスクトップアプリを開発している。
Mac OS 環境では make できたものの、windows 環境では以下のようなエラーが発生して make できない...
❯ Making distributables
✖ Making a squirrel distributable for win32/x64
› ENOENT: no such file or directory, open 'C:\Users\…
An unhandled rejection has occurred inside Forge:
Error: ENOENT: no such file or directory, open 'C:\Users...
解決までの道のりをメモっていく

エラーが起きてるのは、@electron-forge/maker-squirrel
だな
現状の forge.config.ts
はこんな感じ↓
import { MakerSquirrel } from '@electron-forge/maker-squirrel';
//...
const config: ForgeConfig = {
//...
makers: [
new MakerSquirrel({}),
//...
],
};
テンプレートから生成されたものをそのまま利用している

@electron-forge/maker-squirrel
electron-forge 公式 Docs の squirrel のページ読む
Create a Windows installer for your Electron app using Electron Forge.
とりあえず、squirrel は windows installer を作るやつであると
内部で Squirrel.Windows を利用している↓

Mandatory metadata
Squirrel.Windows requires mandatory package metadata to satisfy the .nuspec manifest format.
必須の設定項目があるのか
package.json の必須項目
By default, the Squirrel.Windows maker fetches the author and description fields in the project's package.json file.
package.json の author
と descripton
が必須なのか!どっちも設定してなかったぞ
{
// ...
"author": "Alice and Bob",
"description": "An example Electron app"
// ...
}
forge config で設定可能
Alternatively, you can also override these values directly in your Squirrel.Windows maker config.
package.json の代わりに forge config でも設定可能。
今回は package.json ではなく、forge.config.ts で設定していく
const config: ForgeConfig = {
//...
makers: [
new MakerSquirrel({
authors: 'My App Inc.',
description: 'My Electron application',
}),
//...
],
//...
};
設定したものの、依然同様のエラーが出る...

その他に目ぼしい情報はない...

author と description を付与する対応策しか書いていない


the error occurs when you have a space in your Windows username
windows username にスペースがあるといけないよ、とのことだが、自分の環境では別にスペースはない....

MakerSquirrel の設定項目を見る
The Squirrel.Windows maker inherits all of its config options from the electron-winstaller module, except for appDirectory and outputDirectory, which are set by the maker.
electron-winstaller の設定項目とほぼ同じ (appDirectory
と outputDirectory
は除く)
型の詳細
型はこちら↓
//...
import { convertVersion, createWindowsInstaller, Options as ElectronWinstallerOptions } from 'electron-winstaller';
//...
export type MakerSquirrelConfig = Omit<ElectronWinstallerOptions, 'appDirectory' | 'outputDirectory'>;
export default class MakerSquirrel extends MakerBase<MakerSquirrelConfig> {
//...
export interface SquirrelWindowsOptions {
/**
* The folder path of your Electron app
*/
appDirectory: string;
/**
* The folder path to create the .exe installer in.
*
* Defaults to the installer folder at the project root.
*/
outputDirectory?: string;
/**
* The local path to a `.gif` file to display during install.
*/
loadingGif?: string;
/**
* The authors value for the nuget package metadata.
*
* Defaults to the `author` field from your app's package.json file when unspecified.
*/
authors?: string;
/**
* The owners value for the nuget package metadata.
*
* Defaults to the `authors` field when unspecified.
*/
owners?: string;
/**
* The copyright value for the nuget package metadata.
*
* Defaults to a generated copyright with `authors` or `owners`.
*/
copyright?: string;
/**
* The name of your app's main `.exe` file.
*
* This uses the `name` field in your app's package.json file with an added `.exe` extension when unspecified.
*/
exe?: string;
/**
* The description value for the nuget package metadata.
*
* Defaults to the `description` field from your app's package.json file when unspecified.
*/
description?: string;
/**
* The version value for the nuget package metadata.
*
* Defaults to the `version` field from your app's package.json file when unspecified.
*/
version?: string;
/**
* The title value for the nuget package metadata.
*
* Defaults to the `productName` field and then the `name` field from your app's package.json file when unspecified.
*/
title?: string;
/**
* Windows Application Model ID (appId).
*
* Defaults to the name field in your app's package.json file.
*/
name?: string;
/**
* The path to an Authenticode Code Signing Certificate
*/
certificateFile?: string;
/**
* The password to decrypt the certificate given in `certificateFile`
*/
certificatePassword?: string;
/**
* Params to pass to signtool.
*
* Overrides `certificateFile` and `certificatePassword`.
*/
signWithParams?: string;
/**
* A publicly accessible, fully qualified HTTP(S) URL to an ICO file, used as the application icon
* displayed in Control Panel ➡ Programs and Features. The icon is retrieved at install time.
* Example: http://example.com/favicon.ico
*
* Does not accept `file:` URLs.
*
* Defaults to the Electron icon.
*/
iconUrl?: string;
/**
* The ICO file to use as the icon for the generated Setup.exe
*/
setupIcon?: string;
/**
* The name to use for the generated Setup.exe file
*/
setupExe?: string;
/**
* The name to use for the generated Setup.msi file
*/
setupMsi?: string;
/**
* Should Squirrel.Windows create an MSI installer?
*/
noMsi?: boolean;
/**
* Should Squirrel.Windows delta packages? (disable only if necessary, they are a Good Thing)
*/
noDelta?: boolean;
/**
* A URL to your existing updates. If given, these will be downloaded to create delta updates
*/
remoteReleases?: string;
/**
* Authentication token for remote updates
*/
remoteToken?: string;
usePackageJson?: boolean;
frameworkVersion?: string;
fixUpPaths?: boolean;
skipUpdateIcon?: boolean;
}

file path に関連ありそうなのは、appDirectory, outputDirectory, name くらい

解決
原因
package.json の name に /
が含まれていたことが原因
解決方法
forge.config.ts で name に /
が含まれない値を設定
const config: ForgeConfig = {
//...
makers: [
new MakerSquirrel({
name: "my-app-name",
authors: 'My App Inc.',
description: 'My Electron application',
}),
//...
],
//...
};
詳細説明
今回の project は monorepo の一部で @my-group/desktop-app-name
のような値を package.json の name に指定していた。
詳しいコードまでは追ってないが、"ENOENT no such file or directory, open ..." のエラーが生じた file の path にこの package.json の name が使われていた。
この値を "/" が含まれない "my-app-name" のような値に変更したところうまくいった。

ちなみに、name にスペースが存在してもエラーになるので注意
"my app" を name に指定した場合のエラー↓
The package ID 'my app' contains invalid characters. Examples of valid package IDs include 'MyPackage' and 'MyPackage.Sample'.