laurent22/joplin · error · Error
You must specify a src for each screenshot
Error message
You must specify a src for each screenshot
What it means
Thrown by validateScreenshots() when iterating the manifest's `screenshots` array. Every screenshot object must have a `src` property pointing at the image file (or URL). Missing src is treated as a malformed manifest and aborts the build before any further checks (type, size) run.
Source
Thrown at packages/generator-joplin/generators/app/templates/webpack.config.js:103
console.info(chalk.cyan('Could not get git commit (not a git repo?):', messages[0].trim()));
console.info(chalk.cyan('Git information will not be stored in plugin info file'));
return '';
}
}
function validateCategories(categories) {
if (!categories) return null;
if ((categories.length !== new Set(categories).size)) throw new Error('Repeated categories are not allowed');
// eslint-disable-next-line github/array-foreach -- Old code before rule was applied
categories.forEach(category => {
if (!allPossibleCategories.map(category => { return category.name; }).includes(category)) throw new Error(`${category} is not a valid category. Please make sure that the category name is lowercase. Valid categories are: \n${allPossibleCategories.map(category => { return category.name; })}\n`);
});
}
function validateScreenshots(screenshots) {
if (!screenshots) return null;
for (const screenshot of screenshots) {
if (!screenshot.src) throw new Error('You must specify a src for each screenshot');
// Avoid attempting to download and verify URL screenshots.
if (screenshot.src.startsWith('https://') || screenshot.src.startsWith('http://')) {
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`);
}
}
View on GitHub (pinned to 2654b33620)
Solutions
- Open manifest.json and add a `src` field to every object in the `screenshots` array.
- Verify the key is exactly `src` (not `source`, `path`, `url`).
- For local files confirm the path is relative to the project root and the file exists; for remote images use a full https:// or http:// URL (those skip local checks downstream).
- Re-run the build.
Example fix
// before (manifest.json)
"screenshots": [{ "caption": "Main view" }]
// after
"screenshots": [{ "src": "screenshots/main.png", "caption": "Main view" }] Defensive patterns
Strategy: validation
Validate before calling
// Pre-check every screenshot has a non-empty src.
const manifest = require('./manifest.json');
for (const s of manifest.screenshots || []) {
if (!s.src || typeof s.src !== 'string') throw new Error(`Screenshot missing src: ${JSON.stringify(s)}`);
} Type guard
const hasSrc = (s) => !!s && typeof s.src === 'string' && s.src.length > 0;
Try / catch
try { validateScreenshots(manifest.screenshots); }
catch (e) { if (/specify a src/.test(e.message)) { /* prompt author for missing src */ } else throw e; } Prevention
- Use a manifest schema (JSON Schema) that requires src on every screenshot entry and validate in CI.
- When templating manifest.json from a scaffold, default src to a placeholder rather than omitting it.
When it happens
Trigger: readManifest() -> validateScreenshots(output.screenshots) -> for a screenshot object, `!screenshot.src` is truthy (undefined, empty string, or null).
Common situations: Author adds a screenshot entry with only a `caption` or wrong key name (e.g. 'path' instead of 'src'); copies a template entry and forgets to fill in the path; manifest.json was hand-edited and the key was accidentally removed.
Related errors
- ${category} is not a valid category. Please make sure that t
- ${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}
- Plugin archive was not created because the "dist" directory
AI-assisted analysis of laurent22/joplin@2654b33620 (2026-08-12).
Data as JSON: /api/errors/e05775e8779803f9.
Report an issue: GitHub.