{"record":{"id":"dd63d8b5f0b97e58","repo":"laurent22/joplin","slug":"unknown-command-cmd","errorCode":null,"errorMessage":"Unknown command: ${cmd}","messagePattern":"Unknown command: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/app-cli/app/app-gui.ts","lineNumber":556,"sourceCode":"\t\t\t\tif (this.consoleIsMaximized()) {\n\t\t\t\t\tthis.hideConsole();\n\t\t\t\t} else {\n\t\t\t\t\tthis.maximizeConsole();\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (cmd === 'toggle_metadata') {\n\t\t\tthis.toggleNoteMetadata();\n\t\t} else if (cmd === 'toggle_ids') {\n\t\t\tthis.toggleFolderIds();\n\t\t} else if (cmd === 'toggle_folder_collapse') {\n\t\t\tthis.toggleFolderCollapse();\n\t\t} else if (cmd === 'enter_command_line_mode') {\n\t\t\tconst inputCmd = await this.widget('statusBar').prompt();\n\t\t\tif (!inputCmd) return;\n\t\t\tthis.addCommandToConsole(inputCmd);\n\t\t\tawait this.processPromptCommand(inputCmd);\n\t\t} else {\n\t\t\tthrow new Error(`Unknown command: ${cmd}`);\n\t\t}\n\t}\n\n\tpublic async processPromptCommand(cmd: string) {\n\t\tif (!cmd) return;\n\t\tcmd = cmd.trim();\n\t\tif (!cmd.length) return;\n\n\t\t// this.logger().debug('Got command: ' + cmd);\n\n\t\ttry {\n\t\t\tconst note = this.widget('noteList').currentItem;\n\t\t\tconst folder = this.widget('folderList').currentItem;\n\t\t\tconst args = splitCommandString(cmd);\n\n\t\t\tfor (let i = 0; i < args.length; i++) {\n\t\t\t\tif (args[i] === '$n') {\n\t\t\t\t\targs[i] = note ? note.id : '';","sourceCodeStart":538,"sourceCodeEnd":574,"githubUrl":"https://github.com/laurent22/joplin/blob/2654b33620775080d1d59c552259d41e33dad3d2/packages/app-cli/app/app-gui.ts#L538-L574","documentation":"app-gui.ts dispatches internal GUI commands (triggered by keybindings, e.g. toggle_metadata, toggle_ids, enter_command_line_mode) through an if/else-if chain keyed on the command name. When the dispatched command string matches none of the branches, it throws 'Unknown command'. These are internal GUI action names, not user-typed CLI commands.","triggerScenarios":"A keybinding configuration or internal code calls this dispatch method with a command string that has no matching 'else if (cmd === ...)' branch — for example after adding a new keybinding but forgetting to add the handler, or after renaming a command without updating all references.","commonSituations":"Developer adds a keybinding that emits a new command name but omits the handler branch; a stale/imported keymap references a renamed command; a plugin injects a command name the GUI does not implement.","solutions":["Add the missing 'else if (cmd === \"<name>\") { ... }' branch that the dispatcher expects.","Search the codebase for the command string to find which keybinding/config emits it and verify the spelling matches a branch.","Refactor the if/else-if chain into a Map<string, handler> lookup so missing entries are caught at registration time rather than at dispatch."],"exampleFix":"// before\n//   } else {\n//     throw new Error(`Unknown command: ${cmd}`);\n//   }\n// after\n//   const handlers = { toggle_metadata: () => this.toggleNoteMetadata(), /* ... */ };\n//   const handler = handlers[cmd];\n//   if (!handler) throw new Error(`Unknown command: ${cmd}`);\n//   await handler.call(this);","handlingStrategy":"validation","validationCode":"const knownCommands = new Set(['toggle_metadata', 'toggle_ids', 'toggle_folder_collapse', 'enter_command_line_mode' /* ... */]);\nif (!knownCommands.has(cmd)) {\n  console.warn(`Ignoring unknown GUI command: ${cmd}`);\n  return;\n}","typeGuard":"const isKnownGuiCommand = (cmd: string): boolean =>\n  ['toggle_metadata', 'toggle_ids', 'toggle_folder_collapse', 'enter_command_line_mode'].includes(cmd);","tryCatchPattern":"try {\n  await this.dispatchGuiCommand(cmd);\n} catch (error) {\n  this.logger().warn('GUI command failed:', error.message);\n}","preventionTips":["Prefer a Map<string, handler> dispatch table over an if/else-if chain so new commands are added in one place.","When adding a keybinding, add the matching handler branch in the same commit.","Unit-test that every keybinding command string has a corresponding handler."],"tags":["terminal-gui","command-dispatch","keybinding","programming-error"],"backgroundTag":null,"analyzedSha":"2654b33620775080d1d59c552259d41e33dad3d2","analyzedAt":"2026-08-12T14:26:46.263Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}