laurent22/joplin · error · Error

Invalid command: "%s"

Error message

Invalid command: "%s"

What it means

Terminal fallback throw at the end of the `tag` command's if/else chain: if `args['tag-command']` is not one of `add`, `remove`, `list`, or `notetags`, execution reaches the else and throws. The invalid command value is interpolated via `%s` so the user sees what they typed. This is an enum-validation failure on the subcommand.

Source

Thrown at packages/app-cli/app/command-tag.ts:94

			} else {
				const tags: TagEntity[] = await Tag.all();
				tags.map(tag => {
					this.stdout(tag.title);
				});
			}
		} else if (command === 'notetags') {
			if (args.tag) {
				const note = await app().loadItem(ModelType.Note, args.tag);
				if (!note) throw new Error(_('Cannot find "%s".', args.tag));
				const tags: TagEntity[] = await Tag.tagsByNoteId(note.id);
				tags.map(tag => {
					this.stdout(tag.title);
				});
			} else {
				throw new Error(_('Cannot find "%s".', ''));
			}
		} else {
			throw new Error(_('Invalid command: "%s"', command));
		}
	}
}

module.exports = Command;

View on GitHub (pinned to 2654b33620)

Solutions

  1. Use one of the supported subcommands: add, remove, list, notetags.
  2. Run `:help tag` to see the current usage string.
  3. When scripting, validate `tag-command` against the known set before invoking.

Example fix

// before
throw new Error(_('Invalid command: "%s"', command));

// after - list valid commands in the message
throw new Error(_('Invalid tag-command: "%s". Valid commands: add, remove, list, notetags.', command));
Defensive patterns

Strategy: validation

Validate before calling

const VALID = ['add','remove','list','notetags'];
if (!VALID.includes(command)) {
	throw new Error(`Invalid tag-command "${command}". Valid: ${VALID.join(', ')}`);
}

Type guard

const isTagCommand = (c: string): c is 'add'|'remove'|'list'|'notetags' =>
	['add','remove','list','notetags'].includes(c);

Try / catch

try {
	await app().executeCommand(['tag', subcommand, tag, note].filter(Boolean));
} catch (e) {
	if (/Invalid command/.test(e.message)) { /* show help, reprompt */ }
	else throw e;
}

Prevention

When it happens

Trigger: Running `:tag foo ...` or any unrecognized first token; casing mismatch (matching is exact lowercase); passing a subcommand from outdated documentation that no longer exists.

Common situations: Typo in the subcommand; using `tags`/`delete`/`rm` instead of the supported `add`/`remove`/`list`/`notetags`; empty `tag-command` from a malformed invocation.

Related errors


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