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
- Read the error — it prints both `name` and the resolved `fullPath`; create the file at that exact path.
- Verify filename casing matches exactly (src/Foo.js vs src/foo.js).
- If the entry in plugin.config.json is wrong, correct or remove it.
- 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
- Keep plugin.config.json's extraScriptOptions keys in sync with files in src/ via a pre-build check.
- On case-sensitive filesystems, treat filename casing as significant and lint against mismatches.
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
- ${category} is not a valid category. Please make sure that t
- You must specify a src for each screenshot
- ${screenshotType} is not a valid screenshot type. Valid type
- Max screenshot file size is ${fileMaxSize}KB. ${screenshotPa
- Manifest plugin ID is not set in ${manifestPath}
AI-assisted analysis of laurent22/joplin@2654b33620 (2026-08-12).
Data as JSON: /api/errors/842a3a85c855b889.
Report an issue: GitHub.