SonarSource/sonarqube · error · NotFoundException
Plugin not found
Error message
Plugin %s not found
What it means
DownloadAction serves api/plugins/download, streaming a plugin's JAR from the server's plugin repository. If no installed server plugin matches the requested plugin key, the plugin is not present in the local repository and the action throws NotFoundException.
Solutions
- Verify the plugin key with GET api/plugins/installed (or api/plugins/available) and use the exact key returned.
- If the plugin should be installed, install it first (marketplace UI or api/plugins/install) and retry the download.
- If the plugin was just uninstalled or is pending a restart, restart the server so the repository state matches, or download the JAR from the update center instead.
Example fix
// before
const jar = await api.plugins.download({ plugin: 'sonar-go-plugin' });
// after
const installed = await api.plugins.installed();
const p = installed.plugins.find(p => p.key === 'sonar-go-plugin');
if (!p) throw new Error(`plugin not installed: ${key}`);
const jar = await api.plugins.download({ plugin: p.key }); Defensive patterns
Strategy: validation
Validate before calling
const installed = (await api.plugins.installed()).plugins;
const plugin = installed.find(p => p.key === key);
if (!plugin) throw new Error(`plugin ${key} not installed; cannot download`); Type guard
function isInstalled(plugins, key) {
return Array.isArray(plugins) && plugins.some(p => p && p.key === key);
} Try / catch
try {
return await api.plugins.download({ plugin: key });
} catch (e) {
if (e.status === 404) {
throw new Error(`plugin '${key}' not found on server; check api/plugins/installed`);
}
throw e;
} Prevention
- Fetch api/plugins/installed first and use exact keys from its response.
- Handle pending-install/pending-uninstall states before downloading.
- Prefer the update center artifacts for plugins not installed on the server.
When it happens
Trigger: GET api/plugins/download?plugin=<key> where <key> is misspelled, refers to a plugin that is not installed on this server, or was uninstalled/pending removal (plugin JAR not currently loaded in the repository).
Common situations: Scripts downloading plugin JARs after an update-center listing where the key from the marketplace differs from the installed key; downloading a plugin that is only bundled (e.g. commercial edition) and thus not in the server plugin repository; stale automation referencing an uninstalled plugin.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
- Analysis ' ' not found
- Can't install plugin without accepting firstly plugins risk…
- Issue with key ' ' does not exist
- Metrics are not found
- No plugin with key ' ' or plugin ' ' is already installed…
AI-assisted analysis of SonarSource/sonarqube@184c821202 (2026-09-09).
Data as JSON: /api/errors/fde882815615e492.
Report an issue: GitHub.
Appendix: source
Thrown at server/sonar-webserver-webapi/src/main/java/org/sonar/server/plugins/ws/DownloadAction.java:67
.setInternal(true)
.setContentType(Response.ContentType.BINARY)
.setHandler(this);
action.createParam(PLUGIN_PARAM)
.setRequired(true)
.setDescription("The key identifying the plugin to download")
.setExampleValue("cobol");
action.setChangelog(new Change("9.8", "Parameter 'acceptCompressions' removed"));
}
@Override
public void handle(Request request, Response response) throws Exception {
String pluginKey = request.mandatoryParam(PLUGIN_PARAM);
Optional<ServerPlugin> file = pluginRepository.findPlugin(pluginKey);
if (!file.isPresent()) {
throw new NotFoundException("Plugin " + pluginKey + " not found");
}
FileAndMd5 downloadedFile;
response.stream().setMediaType("application/java-archive");
downloadedFile = file.get().getJar();
response.setHeader("Sonar-MD5", downloadedFile.getMd5());
try (InputStream input = FileUtils.openInputStream(downloadedFile.getFile())) {
IOUtils.copyLarge(input, response.stream().output());
}
}
}
View on GitHub (pinned to 184c821202)