laurent22/joplin · error · Error

Could not find extra script: "${name}" at "${fullPath}"

Error message

Could not find extra script: "${name}" at "${fullPath}"

What it means

Thrown by resolveExtraScriptPath() for each extra script declared in plugin.config.json. The script must exist at `./src/${name}` relative to rootDir. fs.pathExistsSync returning false aborts before webpack entry config is built.

Source

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

	resolve: {
		fallback: moduleFallback,
	},
	output: {
		filename: 'index.js',
		path: publishDir,
	},
	plugins: [{
		apply(compiler) {
			compiler.hooks.done.tap('archiveOnBuildListener', onBuildCompleted);
		},
	}],
};

function resolveExtraScriptPath(name) {
	const relativePath = `./src/${name}`;

	const fullPath = path.resolve(`${rootDir}/${relativePath}`);
	if (!fs.pathExistsSync(fullPath)) throw new Error(`Could not find extra script: "${name}" at "${fullPath}"`);

	const s = name.split('.');
	s.pop();
	const nameNoExt = s.join('.');

	return {
		entry: relativePath,
		output: {
			filename: `${nameNoExt}.js`,
			path: distDir,
			library: 'default',
			libraryTarget: 'commonjs',
			libraryExport: 'default',
		},
	};
}

function buildExtraScriptConfigs(userConfig) {

View on GitHub (pinned to 2654b33620)

Solutions

  1. Read the error — it prints both `name` and the resolved `fullPath`; create the file at that exact path.
  2. Verify filename casing matches exactly (src/Foo.js vs src/foo.js).
  3. If the entry in plugin.config.json is wrong, correct or remove it.
  4. Re-run the build.

Example fix

// plugin.config.json (before)
{ "extraScriptOptions": { "markdownItTestPlugin.js": {} } }
// src/ has markdownItPlugin.js (typo)
// after: create src/markdownItTestPlugin.js OR fix the name in plugin.config.json
Defensive patterns

Strategy: validation

Validate before calling

const fs = require('fs-extra');
const path = require('path');
for (const name of Object.keys(pluginConfig.extraScriptOptions || {})) {
  const full = path.resolve(rootDir, 'src', name);
  if (!fs.pathExistsSync(full)) throw new Error(`Missing extra script file: ${full}`);
}

Type guard

const extraScriptExists = (name, rootDir) => fs.pathExistsSync(path.resolve(rootDir, 'src', name));

Try / catch

try { resolveExtraScriptPath(name); }
catch (e) { if (/Could not find extra script/.test(e.message)) { /* create file or fix plugin.config.json */ } else throw e; }

Prevention

When it happens

Trigger: plugin.config.json lists an extra script (e.g. "markdownItTestPlugin.js") and the file is absent from src/, misnamed, or in a different directory.

Common situations: Author edited plugin.config.json but did not create the matching file; filename casing differs on case-sensitive filesystems; file was moved to a subfolder.

Related errors


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