laurent22/joplin · error · Error
Manifest plugin ID is not set in ${manifestPath}
Error message
Manifest plugin ID is not set in ${manifestPath} What it means
Thrown by readManifest() right after JSON.parse of manifest.json. The plugin id is the unique identifier used by Joplin to register and update the plugin; it cannot be empty. The check is `if (!output.id)`, so missing, empty-string, or null all trigger it.
Source
Thrown at packages/generator-joplin/generators/app/templates/webpack.config.js:125
continue;
}
const screenshotType = screenshot.src.split('.').pop();
if (!allPossibleScreenshotsType.includes(screenshotType)) throw new Error(`${screenshotType} is not a valid screenshot type. Valid types are: \n${allPossibleScreenshotsType}\n`);
const screenshotPath = path.resolve(rootDir, screenshot.src);
// Max file size is 1MB
const fileMaxSize = 1024;
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,View on GitHub (pinned to 2654b33620)
Solutions
- Open manifest.json and add a unique `id` (typically a reverse-DNS or slug-style identifier, e.g. "com.example.my-plugin").
- Ensure the id is unique across the Joplin plugin repository to avoid collisions.
- Re-run the build.
Example fix
// before (manifest.json)
{ "version": "1.0.0", "app_min_version": "2.6" }
// after
{ "id": "com.example.my-plugin", "version": "1.0.0", "app_min_version": "2.6" } Defensive patterns
Strategy: validation
Validate before calling
const manifest = require('./manifest.json');
if (!manifest.id || typeof manifest.id !== 'string') {
throw new Error('manifest.json must define a non-empty string `id`');
} Type guard
const hasId = (m) => !!m && typeof m.id === 'string' && m.id.length > 0;
Try / catch
try { readManifest(manifestPath); }
catch (e) { if (/plugin ID is not set/.test(e.message)) { /* prompt for an id */ } else throw e; } Prevention
- Enforce a JSON Schema requiring a non-empty `id` on manifest.json in CI.
- Never delete the id field when editing manifest.json; keep it under version control and review diffs.
When it happens
Trigger: manifest.json parses successfully but has no `id` field, or `id` is set to "" or null.
Common situations: New plugin scaffold where the id was not filled in; field accidentally deleted during a manual edit; key renamed to `pluginId` or `name`.
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
- Plugin archive was not created because the "dist" directory
AI-assisted analysis of laurent22/joplin@2654b33620 (2026-08-12).
Data as JSON: /api/errors/186ed40e815139ee.
Report an issue: GitHub.