laurent22/joplin · error · Error
Ambiguous notebook "%s". Please use short notebook id instea
Error message
Ambiguous notebook "%s". Please use short notebook id instead - press "ti" to see the short notebook id
What it means
Thrown by `validDestinationFolder` (used by `mkbook -p`) after a folder *was* found by exact title/id, but `Folder.search({ titlePattern: targetFolder, limit: 2 })` returns more than one row. search uses SQL LIKE matching, so the parent string also matches other notebooks whose titles contain it. loadItem (exact title or id) succeeded, but the LIKE search reveals the name is ambiguous across the catalog.
Source
Thrown at packages/app-cli/app/command-mkbook.ts:33
}
public options() {
return [
['-p, --parent <parent-notebook>', _('Create a new notebook under a parent notebook.')],
];
}
// validDestinationFolder check for presents and ambiguous folders
public async validDestinationFolder(targetFolder: string) {
const destinationFolder = await app().loadItem(ModelType.Folder, targetFolder);
if (!destinationFolder) {
throw new Error(_('Cannot find: "%s"', targetFolder));
}
const destinationDups = await Folder.search({ titlePattern: targetFolder, limit: 2 });
if (destinationDups.length > 1) {
throw new Error(_('Ambiguous notebook "%s". Please use short notebook id instead - press "ti" to see the short notebook id', targetFolder));
}
return destinationFolder;
}
public async saveAndSwitchFolder(newFolder: FolderEntity) {
const folder = await Folder.save(newFolder, { userSideValidation: true });
app().switchCurrentFolder(folder);
}
public async action(args: { 'new-notebook': string; options: { parent?: string } }) {
const targetFolder = args.options.parent;
const newFolder: FolderEntity = {
title: args['new-notebook'],
};View on GitHub (pinned to 2654b33620)
Solutions
- Use the short notebook id: press `ti` in the GUI to reveal ids, then `mkbook -p <short-id> <new>`
- Rename the colliding notebooks to disambiguate titles
- Use the full 32-char folder id
Example fix
// before joplin mkbook -p Note SubBook // Note LIKE-matches "Notes" and "My Notes" -> throws // after joplin mkbook -p 7f3a SubBook // short id is unambiguous
Defensive patterns
Strategy: validation
Validate before calling
import Folder from '@joplin/lib/models/Folder';
async function assertParentUnambiguous(parentRef: string) {
const dups = await Folder.search({ titlePattern: parentRef, limit: 2 });
if (dups.length > 1) {
throw new Error(`Parent "${parentRef}" is ambiguous (${dups.length}+ matches). Use the short notebook id.`);
}
} Type guard
const isUnambiguous = async (ref: string): Promise<boolean> =>
(await Folder.search({ titlePattern: ref, limit: 2 })).length <= 1; Prevention
- Use short notebook ids (toggle with `ti`) for `-p` whenever titles overlap
- Avoid short parent names that are substrings of other notebook titles
- Rename colliding notebooks to disambiguate the catalog
When it happens
Trigger: Parent name is a substring of other notebook titles (e.g., `-p Note` when "Notes" and "My Notes" both exist); short parent strings that LIKE-match widely; duplicated exact titles across the tree (less common because loadItem itself would have thrown 'More than one item match' first).
Common situations: Notebook hierarchies with overlapping names; abbreviated parent references in scripts.
Related errors
- Cannot find: "%s"
- Ambiguous notebook "%s". Please use short notebook id instea
- Ambiguous notebook "%s". Please use notebook id instead - pr
- Cannot find "%s".
- Cannot find "%s".
AI-assisted analysis of laurent22/joplin@2654b33620 (2026-08-12).
Data as JSON: /api/errors/1f5a011e1d7cd357.
Report an issue: GitHub.