laurent22/joplin · error · Error

Plugin archive was not created because the "dist" directory

Error message

Plugin archive was not created because the "dist" directory is empty

What it means

Thrown by createPluginArchive() when glob.sync over `${sourceDir}/**/*` returns zero files. The dist directory is expected to contain the built plugin output before archiving into the .jpl tar. An empty dist means there is nothing to ship.

Source

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

		const fileSize = fs.statSync(screenshotPath).size / 1024;
		if (fileSize > fileMaxSize) throw new Error(`Max screenshot file size is ${fileMaxSize}KB. ${screenshotPath} is ${fileSize}KB`);
	}
}

function readManifest(manifestPath) {
	const content = fs.readFileSync(manifestPath, 'utf8');
	const output = JSON.parse(content);
	if (!output.id) throw new Error(`Manifest plugin ID is not set in ${manifestPath}`);
	validateCategories(output.categories);
	validateScreenshots(output.screenshots);
	return output;
}

function createPluginArchive(sourceDir, destPath) {
	const distFiles = glob.sync(`${sourceDir}/**/*`, { nodir: true, windowsPathsNoEscape: true })
		.map(f => f.substr(sourceDir.length + 1));

	if (!distFiles.length) throw new Error('Plugin archive was not created because the "dist" directory is empty');
	fs.removeSync(destPath);

	tar.create(
		{
			strict: true,
			portable: true,
			file: destPath,
			cwd: sourceDir,
			sync: true,
		},
		distFiles,
	);

	console.info(chalk.cyan(`Plugin archive has been created in ${destPath}`));
}

const writeManifest = (manifestPath, content) => {
	fs.writeFileSync(manifestPath, JSON.stringify(content, null, '\t'), 'utf8');

View on GitHub (pinned to 2654b33620)

Solutions

  1. Run the build step first (e.g. `npm run build` / `yarn build`) so dist/ is populated before archiving.
  2. Verify dist/ actually contains the emitted index.js and assets (ls dist).
  3. Check webpack output.path matches the sourceDir passed to createPluginArchive.
  4. If the build step failed, fix the upstream error before re-running dist.

Example fix

# before
npm run dist   # dist/ is empty
# after
npm run build && npm run dist
Defensive patterns

Strategy: validation

Validate before calling

const fs = require('fs');
const path = require('path');
const hasFiles = (dir) => fs.existsSync(dir) && fs.readdirSync(dir).some(f => fs.statSync(path.join(dir, f)).isFile());
if (!hasFiles(distDir)) throw new Error('dist/ is empty — run the build step first');

Type guard

const distHasOutput = (dir) => fs.existsSync(dir) && fs.readdirSync(dir).length > 0;

Try / catch

try { createPluginArchive(distDir, destPath); }
catch (e) { if (/"dist" directory is empty/.test(e.message)) { /* run build, then retry */ } else throw e; }

Prevention

When it happens

Trigger: createPluginArchive(distDir, destPath) is called but distDir contains no files — glob with nodir:true returns an empty array.

Common situations: Build script ran `npm run dist` before `npm run build`; webpack build failed silently or wrote to a different output dir; dist was cleaned and never rebuilt; misconfigured output.path in webpack.

Related errors


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