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

  1. Use the short notebook id: press `ti` in the GUI to reveal ids, then `mkbook -p <short-id> <new>`
  2. Rename the colliding notebooks to disambiguate titles
  3. 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

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


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