laurent22/joplin · error · Error
Repeated categories are not allowed
Error message
Repeated categories are not allowed
What it means
Thrown by validateCategories (in the plugin template's webpack.config.js) when the manifest.json categories array contains duplicate entries — i.e. categories.length !== new Set(categories).size. Categories classify the plugin on the Joplin plugin registry and duplicates are rejected to keep the listing clean. Validation runs at build time when readManifest parses src/manifest.json.
Source
Thrown at packages/generator-joplin/generators/app/templates/webpack.config.js:93
}
function currentGitInfo() {
try {
let branch = execSync('git rev-parse --abbrev-ref HEAD', { stdio: 'pipe' }).toString().trim();
const commit = execSync('git rev-parse HEAD', { stdio: 'pipe' }).toString().trim();
if (branch === 'HEAD') branch = 'master';
return `${branch}:${commit}`;
} catch (error) {
const messages = error.message ? error.message.split('\n') : [''];
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`);View on GitHub (pinned to 2654b33620)
Solutions
- Open src/manifest.json and remove duplicate entries from the categories array.
- Use a JSON-aware editor or lint the manifest to detect dupes before building.
- De-duplicate programmatically: [...new Set(manifest.categories)].
Example fix
// before — src/manifest.json "categories": ["editor", "productivity", "editor"] // after "categories": ["editor", "productivity"]
Defensive patterns
Strategy: validation
Validate before calling
const manifest = JSON.parse(fs.readFileSync('src/manifest.json', 'utf8'));
if (manifest.categories) {
const set = new Set(manifest.categories);
if (set.size !== manifest.categories.length) {
throw new Error('Duplicate categories in manifest.json');
}
} Type guard
function hasUniqueCategories(cats) {
return Array.isArray(cats) && new Set(cats).size === cats.length;
} Prevention
- De-duplicate categories before building: [...new Set(manifest.categories)].
- Lint manifest.json in a pre-build step.
- Avoid hand-editing the categories array under merge conflicts.
When it happens
Trigger: manifest.json has "categories": ["editor", "editor"] or ["productivity", "productivity", "tags"]; a copy-paste when editing the manifest duplicated an entry; a script regenerated the manifest and inserted a category twice.
Common situations: Plugin author hand-edited manifest.json and duplicated a category; a merge conflict resolution left a doubled entry; a scaffolding/tooling bug wrote the same category twice.
Related errors
- Failed to extract a valid commit hash. Ensure that git is pr
- You are in a detached HEAD state. Checkout a branch (e.g. gi
- Remote HEAD is empty. Make sure you have pushed your changes
- Unexpected git ls-remote output: "${remoteHeadLine}". Make s
- Failed to extract a valid remote commit hash.
AI-assisted analysis of laurent22/joplin@2654b33620 (2026-08-12).
Data as JSON: /api/errors/1aa00a43114eebe7.
Report an issue: GitHub.