laurent22/joplin · error · Error

Cannot find "%s".

Error message

Cannot find "%s".

What it means

Thrown by `help <command>` when `app().findCommandByName(args.command)` returns falsy. In practice findCommandByName (app.ts:227) returns the cached command, or requires `command-<name>.js`, or throws a typed `notFound` error if the module is missing. The `if (!command)` guard at command-help.ts:66 is defensive and only fires if the require returns a falsy module export — extremely rare in normal operation; the common 'unknown command' case is reported via the notFound error, not this one.

Source

Thrown at packages/app-cli/app/command-help.ts:66

				.gui()
				.keymap();

			const rows = [];

			for (let i = 0; i < keymap.length; i++) {
				const item = keymap[i];
				const keys = item.keys.map((k: string) => (k === ' ' ? '(SPACE)' : k));
				rows.push([keys.join(', '), item.command]);
			}

			cliUtils.printArray(this.stdout.bind(this), rows);
		} else if (args.command === 'all') {
			const commands = this.allCommands();
			const output = commands.map(c => renderCommandHelp(c));
			this.stdout(output.join('\n\n'));
		} else if (args.command) {
			const command = app().findCommandByName(args['command']);
			if (!command) throw new Error(_('Cannot find "%s".', args.command));
			this.stdout(renderCommandHelp(command, stdoutWidth));
		} else {
			const commandNames = this.allCommands().map(a => a.name());

			this.stdout(_('Type `help [command]` for more information about a command; or type `help all` for the complete usage information.'));
			this.stdout('');
			this.stdout(_('The possible commands are:'));
			this.stdout('');
			this.stdout(commandNames.join(', '));
			this.stdout('');
			this.stdout(_('In any command, a note or notebook can be referred to by title or ID, or using the shortcuts `$n` or `$b` for, respectively, the currently selected note or notebook. `$c` can be used to refer to the currently selected item.'));
			this.stdout('');
			this.stdout(_('To move from one pane to another, press Tab or Shift+Tab.'));
			this.stdout(_('Use the arrows and page up/down to scroll the lists and text areas (including this console).'));
			this.stdout(_('To maximise/minimise the console, press "tc".'));
			this.stdout(_('To enter command line mode, press ":"'));
			this.stdout(_('To exit command line mode, press ESCAPE'));
			this.stdout(_('For the list of keyboard shortcuts and config options, type `help keymap`'));

View on GitHub (pinned to 2654b33620)

Solutions

  1. Run `joplin help` (no args) to list the actually-registered command names
  2. Clear the command metadata cache (remove `~/.config/joplin-dev-desktop/cache.json` / cache db entry keyed 'metadata') and retry
  3. If developing a custom command, verify `module.exports = Command;` exports a truthy class
  4. Check for orphaned `command-*.js` files in the app directory that export null/undefined

Example fix

// before
joplin help bogusThing   // may print "No such command" (notFound) before reaching this guard

// after
joplin help              // lists valid commands
joplin help mknote       // use a name from the list
Defensive patterns

Strategy: try-catch

Validate before calling

import app from './app';

function commandExists(name: string): boolean {
  try {
    return !!app().findCommandByName(name);
  } catch (e: any) {
    if (e?.type === 'notFound') return false;
    throw e;
  }
}

if (!commandExists(args.command)) {
  console.error(`Unknown command "${args.command}". Run \`help\` for the list.`);
}

Type guard

const isRegisteredCommand = (name: string): boolean => {
  try { return !!app().findCommandByName(name); } catch { return false; }
};

Try / catch

try {
  await cli.execCommand(['help', name]);
} catch (e) {
  if (e?.type === 'notFound' || /^Cannot find/.test(e.message)) {
    // list valid commands as a fallback
    await cli.execCommand(['help']);
  } else throw e;
}

Prevention

When it happens

Trigger: A command module whose default export is falsy (broken/empty plugin command file loaded into the commands directory); a stale command cache from a downgraded Joplin version.

Common situations: Almost never hit by end users; mainly a developer/extension-author concern when hand-editing command files. Typos in command names hit the 'notFound' error path instead.

Related errors


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