{"record":{"id":"b348218848e6e59a","repo":"elastic/elasticsearch","slug":"64-b34821","errorCode":"64","errorMessage":"At least one plugin ID is required","messagePattern":"At least one plugin ID is required","errorType":"exception","errorClass":"UserException","httpStatus":null,"severity":"error","filePath":"distribution/tools/plugin-cli/src/main/java/org/elasticsearch/plugins/cli/RemovePluginAction.java","lineNumber":75,"sourceCode":"        this.purge = purge;\n    }\n\n    public void setPurge(boolean purge) {\n        this.purge = purge;\n    }\n\n    /**\n     * Remove the plugin specified by {@code pluginName}.\n     *\n     * @param plugins    the IDs of the plugins to remove\n     * @throws IOException   if any I/O exception occurs while performing a file operation\n     * @throws UserException if plugins is null or empty\n     * @throws UserException if plugin directory does not exist\n     * @throws UserException if the plugin bin directory is not a directory\n     */\n    public void execute(List<InstallablePlugin> plugins) throws IOException, UserException {\n        if (plugins == null || plugins.isEmpty()) {\n            throw new UserException(ExitCodes.USAGE, \"At least one plugin ID is required\");\n        }\n\n        ensurePluginsNotUsedByOtherPlugins(plugins);\n\n        for (InstallablePlugin plugin : plugins) {\n            checkCanRemove(plugin);\n        }\n\n        for (InstallablePlugin plugin : plugins) {\n            removePlugin(plugin);\n        }\n    }\n\n    private void ensurePluginsNotUsedByOtherPlugins(List<InstallablePlugin> plugins) throws IOException, UserException {\n        // First make sure nothing extends this plugin\n        final Map<String, List<String>> usedBy = new HashMap<>();\n\n        // We build a new map where the keys are plugins that extend plugins","sourceCodeStart":57,"sourceCodeEnd":93,"githubUrl":"https://github.com/elastic/elasticsearch/blob/db6a809a667c081ca1dc7500389d26975573215f/distribution/tools/plugin-cli/src/main/java/org/elasticsearch/plugins/cli/RemovePluginAction.java#L57-L93","documentation":"Thrown by RemovePluginAction.execute when the list of plugins to remove is null or empty. The CLI refuses to proceed without at least one target id; exit code is USAGE (64). This is the input-validation gate before ensurePluginsNotUsedByOtherPlugins and per-plugin removal.","triggerScenarios":"execute(List<InstallablePlugin> plugins) is called with null or an empty list; the guard throws UserException(USAGE) immediately. Reached via `elasticsearch-plugin remove` invoked with no plugin ids (and no default), or via programmatic callers that pass an empty list.","commonSituations":"Running `elasticsearch-plugin remove` with no arguments; scripting layer that builds the args from an empty list; argparse equivalent that allows zero ids.","solutions":["Pass one or more plugin ids: `elasticsearch-plugin remove <id> [<id>...]`.","In scripted callers, check the list is non-empty before invoking remove.","If you intended to list plugins, use `elasticsearch-plugin list` instead."],"exampleFix":"# before:\nbin/elasticsearch-plugin remove          # no ids\n# after:\nbin/elasticsearch-plugin remove analysis-icu store-smb","handlingStrategy":"validation","validationCode":"// Ensure non-empty plugin list before calling execute.\nif (plugins == null || plugins.isEmpty()) {\n    throw new IllegalArgumentException(\"At least one plugin id required for removal\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["In scripts, fail fast if the resolved plugin-id list is empty.","Validate CLI arg count before dispatching to RemovePluginAction.","Point users to `list` when no ids are supplied."],"tags":["plugin-remove","validation","usage","plugin-cli"],"analyzedSha":"db6a809a667c081ca1dc7500389d26975573215f","analyzedAt":"2026-08-12T01:39:14.192Z","schemaVersion":2},"datasetVersion":"2026-08-12T06:17:24.410Z"}