laurent22/joplin · error · Error

Cannot find "%s".

Error message

Cannot find "%s".

What it means

Thrown by `restore <pattern>` when `app().loadItems('folderOrNote', pattern)` returns an empty array. loadItems('folderOrNote', ...) tries folders then notes by exact title, full id, partial id >=2 chars. The command then calls `restoreItems(items[0].type_, ids, { useRestoreFolder: true })`. If the pattern matches nothing in the trash (or nothing at all), the array is empty.

Source

Thrown at packages/app-cli/app/command-restore.ts:19

import BaseCommand from './base-command';
import app from './app';
import { _ } from '@joplin/lib/locale';
import restoreItems from '@joplin/lib/services/trash/restoreItems';

class Command extends BaseCommand {
	public override usage() {
		return 'restore <pattern>';
	}

	public override description() {
		return _('Restore the items matching <pattern> from the trash.');
	}

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

		const items = await app().loadItems('folderOrNote', pattern);
		if (!items.length) throw new Error(_('Cannot find "%s".', pattern));

		const ids = items.map(n => n.id);
		await restoreItems(items[0].type_, ids, { useRestoreFolder: true });
	}
}

module.exports = Command;

View on GitHub (pinned to 2654b33620)

Solutions

  1. List trash contents (in the GUI, or query the `notes`/`folders` tables where `deleted_time > 0`) to find exact titles/ids
  2. Use the full or short id of the trashed item
  3. Confirm the item is actually in trash and not already permanently purged

Example fix

// before
joplin restore "Old Note"   // throws if not in trash or typo

// after
# find the trashed item's id (GUI trash view, or DB query), then:
joplin restore <note-id>
Defensive patterns

Strategy: validation

Validate before calling

import app from './app';

async function resolveTrashItems(pattern: string) {
  const items = await app().loadItems('folderOrNote', pattern);
  if (!items.length) throw new Error(`Cannot find "${pattern}" in trash. Verify trash contents or use the id.`);
  // sanity: caller should only feed actually-deleted items
  const allTrashed = items.every(i => !!(i as any).deleted_time);
  if (!allTrashed) throw new Error('Some matched items are not in trash.');
  return items;
}

Type guard

const isTrashCandidate = (i: any): boolean =>
  !!i?.id && typeof i.deleted_time === 'number' && i.deleted_time > 0;

Prevention

When it happens

Trigger: Pattern matches no trashed item; typo; partial id <2 chars; item was never deleted (so it isn't in trash); item already purged from trash by the revision/trash retention.

Common situations: Trying to restore by a title that exists only as a live (non-deleted) item; trash auto-emptyed; wrong partial id.

Related errors


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