laurent22/joplin · error · Error

Cannot find "%s".

Error message

Cannot find "%s".

What it means

Thrown by `ren <item> <name>` when `app().loadItem('folderOrNote', pattern)` returns null. The 'folderOrNote' type (app.ts:86-90) tries folders first, then notes if no folder matched. `encryptionCheck(item)` runs before the null check but is null-safe (base-command.ts:21 guards `if (item && ...)`), so it never throws on null. The throw means neither a folder nor a note matched the pattern.

Source

Thrown at packages/app-cli/app/command-ren.ts:23

import Folder from '@joplin/lib/models/Folder';
import Note from '@joplin/lib/models/Note';

class Command extends BaseCommand {
	public override usage() {
		return 'ren <item> <name>';
	}

	public override description() {
		return _('Renames the given <item> (note or notebook) to <name>.');
	}

	public override async action(args: { item: string; name: string }) {
		const pattern = args['item'];
		const name = args['name'];

		const item = await app().loadItem('folderOrNote', pattern);
		this.encryptionCheck(item);
		if (!item) throw new Error(_('Cannot find "%s".', pattern));

		const newItem = {
			id: item.id,
			title: name,
			type_: item.type_,
		};

		if (item.type_ === BaseModel.TYPE_FOLDER) {
			await Folder.save(newItem);
		} else {
			await Note.save(newItem);
		}
	}
}

module.exports = Command;

View on GitHub (pinned to 2654b33620)

Solutions

  1. List candidates with `joplin ls /` (folders) and `joplin ls` (notes) and copy the exact title or id
  2. Use the full or short id (>=2 chars) of the item
  3. If the item is encrypted, decrypt it first — otherwise you'll hit 'Cannot change encrypted item'

Example fix

// before
joplin ren "Shoping" "Shopping"   // typo in source -> throws

// after
joplin ls
# confirm exact title "Shopping List"
joplin ren "Shopping List" "Groceries"
# or by id:
joplin ren <id> Groceries
Defensive patterns

Strategy: validation

Validate before calling

import app from './app';

async function resolveRenameTarget(pattern: string) {
  const item = await app().loadItem('folderOrNote', pattern);
  if (!item) throw new Error(`Cannot find "${pattern}". Verify with \`ls\` / \`ls /\`.`);
  if ((item as any).encryption_applied) throw new Error('Cannot rename an encrypted item; decrypt it first.');
  return item;
}

Type guard

type FolderOrNote = { id: string; title: string; type_: number };
const isFolderOrNote = (x: any): x is FolderOrNote =>
  !!x && typeof x.id === 'string' && typeof x.title === 'string';

Prevention

When it happens

Trigger: Typo in the item name; item deleted; partial id <2 chars; renaming an encrypted item (hits the encryptionCheck error instead, with message 'Cannot change encrypted item').

Common situations: Rename scripts with stale titles; renaming items that were moved to trash.

Related errors


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