laurent22/joplin · error · Error

A config file must be specified via the…

Error message

A config file must be specified via the --joplin-plugin-config flag

What it means

Thrown by main() in the generated webpack.config.js when the webpack `env` object has no `joplin-plugin-config` key. This flag selects which webpack config to run (buildMain vs buildExtraScripts); without it the runner cannot decide. The template expects it to be injected by the plugin's npm scripts.

Solutions

  1. Use the npm scripts provided by the scaffold (e.g. `npm run build` / `npm run dist`) which pass the flag for you.
  2. If invoking webpack directly, add `--env joplin-plugin-config=dev` (or `prod`).
  3. Check package.json scripts were not overwritten and still pass the flag.

Example fix

// before (custom command)
webpack --config webpack.config.js
// after
webpack --env joplin-plugin-config=dev --config webpack.config.js
Defensive patterns

Strategy: validation

Validate before calling

// In a wrapper script, ensure the env flag is present before invoking webpack.
const configName = process.env.JOPLIN_PLUGIN_CONFIG || (process.argv.includes('--joplin-plugin-config') ? process.argv[process.argv.indexOf('--joplin-plugin-config') + 1] : null);
if (!configName) throw new Error('Missing --joplin-plugin-config=dev|prod');

Type guard

const hasConfigFlag = (argv) => argv.some(a => a.startsWith('--joplin-plugin-config')) || argv.some(a => a.startsWith('--env') && a.includes('joplin-plugin-config'));

Try / catch

try { main(env); }
catch (e) { if (/joplin-plugin-config flag/.test(e.message)) { /* print usage and exit */ } else throw e; }

Prevention

When it happens

Trigger: webpack is invoked without the env flag — e.g. calling `webpack` directly, or a custom script that omits `--env joplin-plugin-config=...`.

Common situations: Author replaced the scaffolded npm scripts; running webpack-dev-server without the flag; upgraded tooling that swallowed the env argument.

Related errors


AI-assisted analysis of laurent22/joplin@2654b33620 (2026-08-12). Data as JSON: /api/errors/fa3ed6511a6532f0. Report an issue: GitHub.

Appendix: source

Thrown at packages/generator-joplin/generators/app/templates/webpack.config.js:348

const updateVersion = () => {
	const packageJson = getPackageJson();
	packageJson.version = increaseVersion(packageJson.version);
	fs.writeFileSync(packageJsonPath, `${JSON.stringify(packageJson, null, 2)}\n`, 'utf8');

	const manifest = readManifest(manifestPath);
	manifest.version = increaseVersion(manifest.version);
	writeManifest(manifestPath, manifest);

	if (packageJson.version !== manifest.version) {
		console.warn(chalk.yellow(`Version numbers have been updated but they do not match: package.json (${packageJson.version}), manifest.json (${manifest.version}). Set them to the required values to get them in sync.`));
	} else {
		console.info(packageJson.version);
	}
};

function main(environ) {
	const configName = environ['joplin-plugin-config'];
	if (!configName) throw new Error('A config file must be specified via the --joplin-plugin-config flag');

	// Webpack configurations run in parallel, while we need them to run in
	// sequence, and to do that it seems the only way is to run webpack multiple
	// times, with different config each time.

	const configs = {
		// Builds the main src/index.ts and copy the extra content from /src to
		// /dist including scripts, CSS and any other asset.
		buildMain: [pluginConfig],

		// Builds the extra scripts as defined in plugin.config.json. When doing
		// so, some JavaScript files that were copied in the previous might be
		// overwritten here by the compiled version. This is by design. The
		// result is that JS files that don't need compilation, are simply
		// copied to /dist, while those that do need it are correctly compiled.
		buildExtraScripts: buildExtraScriptConfigs(userConfig),

		// Ths config is for creating the .jpl, which is done via the plugin, so

View on GitHub (pinned to 2654b33620)