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
- Use one of the supported subcommands: add, remove, list, notetags.
- Run `:help tag` to see the current usage string.
- 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
- Validate the subcommand against the known enum before invoking.
- Subcommand matching is case-sensitive lowercase.
- Surface the full valid set in your error message.
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
- Unknown subcommand: ${args.command}
- [notebook] is required
- [user] is required
- Cannot find "%s".
- Note count must be specified
AI-assisted analysis of laurent22/joplin@2654b33620 (2026-08-12).
Data as JSON: /api/errors/6b79aae080e920ce.
Report an issue: GitHub.