laurent22/joplin · error · Error
Cannot find "%s".
Error message
Cannot find "%s".
What it means
Thrown by `mv <item> <notebook>` when the destination is not the literal string 'root' and `app().loadItem(ModelType.Folder, destination)` returns null. 'root' is special-cased just above and bypasses the lookup (it moves the item to the top level). Folder lookup is global by exact title, full id, or partial id >=2 chars.
Source
Thrown at packages/app-cli/app/command-mv.ts:24
import Note from '@joplin/lib/models/Note';
class Command extends BaseCommand {
public override usage() {
return 'mv <item> [notebook]';
}
public override description() {
return _('Moves the given <item> to [notebook]');
}
public override async action(args: { item: string; 'notebook': string }) {
const pattern = args['item'];
const destination = args['notebook'];
let folder = null;
if (destination !== 'root') {
folder = await app().loadItem(ModelType.Folder, destination);
if (!folder) throw new Error(_('Cannot find "%s".', destination));
}
const destinationDuplicates = await Folder.search({ titlePattern: destination, limit: 2 });
if (destinationDuplicates.length > 1) {
throw new Error(_('Ambiguous notebook "%s". Please use short notebook id instead - press "ti" to see the short notebook id', destination));
}
const itemFolder = await app().loadItem(ModelType.Folder, pattern);
if (itemFolder) {
const sourceDuplicates = await Folder.search({ titlePattern: pattern, limit: 2 });
if (sourceDuplicates.length > 1) {
throw new Error(_('Ambiguous notebook "%s". Please use notebook id instead - press "ti" to see the short notebook id or use $b for current selected notebook', pattern));
}
if (destination === 'root') {
await Folder.moveToFolder(itemFolder.id, '');
} else {
await Folder.moveToFolder(itemFolder.id, folder.id);
}View on GitHub (pinned to 2654b33620)
Solutions
- List notebooks with `joplin ls /` and use the exact title or id
- Use the literal `root` as the destination to move to the top level
- Use the short notebook id (toggle with `ti`)
Example fix
// before joplin mv ProjectA Projcts // typo, throws // after joplin ls / # title is "Projects" joplin mv ProjectA Projects # or move to top level: joplin mv ProjectA root
Defensive patterns
Strategy: validation
Validate before calling
import app from './app';
import { ModelType } from '@joplin/lib/BaseModel';
async function resolveMoveDestination(destRef: string) {
if (destRef === 'root') return null; // top-level move
const folder = await app().loadItem(ModelType.Folder, destRef);
if (!folder) throw new Error(`Cannot find destination notebook "${destRef}". Verify with \`ls /\` or use \`root\`.`);
return folder;
} Type guard
const isFolderOrNullRoot = (f: any, ref: string): boolean => ref === 'root' ? true : (!!f && typeof f.id === 'string');
Prevention
- Use `root` literally when moving to the top level
- Verify destination with `ls /` first
- Prefer notebook ids over titles in scripts
When it happens
Trigger: Typo in the destination notebook name; destination deleted/renamed; partial id <2 chars; forgetting the literal `root` keyword when moving to the top level.
Common situations: Restructuring notebooks and misspelling the target; using a note id where a notebook id is required.
Related errors
- Ambiguous notebook "%s". Please use short notebook id instea
- Ambiguous notebook "%s". Please use notebook id instead - pr
- Cannot find "%s".
- Cannot find: "%s"
- Ambiguous notebook "%s". Please use short notebook id instea
AI-assisted analysis of laurent22/joplin@2654b33620 (2026-08-12).
Data as JSON: /api/errors/93ed997bed137d81.
Report an issue: GitHub.