alibaba/nacos · warning · NacosApiException

RESOURCE_NOT_FOUND

RESOURCE_NOT_FOUND

Error message

Plugin not found: {pluginId}

What it means

PluginManager.setPluginEnabled throws NacosApiException(NacosException.NOT_FOUND 404, ErrorCode.RESOURCE_NOT_FOUND 20004) when the pluginId is absent from pluginRegistry. The pluginId is composed as {type}:{name} (e.g. "trace:test", "auth:nacos"). This method backs PUT /v3/console/plugin/status.

Source

Thrown at core/src/main/java/com/alibaba/nacos/core/plugin/PluginManager.java:241

     * @throws NacosApiException if plugin not found or is critical
     */
    public void setPluginEnabled(String pluginId, boolean enabled) throws NacosApiException {
        setPluginEnabled(pluginId, enabled, false);
    }
    
    /**
     * Set plugin enabled/disabled state.
     *
     * @param pluginId plugin ID
     * @param enabled whether to enable
     * @param localOnly if true, only update local node without Raft sync (for emergency use)
     * @throws NacosApiException if plugin not found or is critical
     */
    public void setPluginEnabled(String pluginId, boolean enabled, boolean localOnly)
        throws NacosApiException {
        PluginInfo info = pluginRegistry.get(pluginId);
        if (info == null) {
            throw new NacosApiException(NacosException.NOT_FOUND, ErrorCode.RESOURCE_NOT_FOUND,
                "Plugin not found: " + pluginId);
        }
        
        try {
            validateRuntimeChangeSupported(info, "state");
            validateStateChangeInternal(info, enabled);
        } catch (IllegalArgumentException e) {
            throw new NacosApiException(NacosException.INVALID_PARAM,
                ErrorCode.PARAMETER_VALIDATE_ERROR, e.getMessage());
        }
        if (info.isEnabled() == enabled) {
            LOGGER.debug("[PluginManager] Plugin {} already has enabled={}", pluginId, enabled);
            return;
        }
        
        // LocalOnly mode: only update local memory, skip cluster sync
        if (localOnly) {
            LOGGER.warn(

View on GitHub (pinned to 9b989acdf1)

Solutions

  1. Call GET /v3/console/plugin/list first and use an exact pluginId/type+name from the result.
  2. Ensure the plugin jar is present on the server classpath and loaded at startup.
  3. Check the server log for plugin load failures.

Example fix

// before
PUT /v3/console/plugin/status?pluginType=auth&pluginName=ldap&enabled=false
// after (verify id first)
GET /v3/console/plugin/list?pluginType=auth  -> use the real pluginName
Defensive patterns

Strategy: validation

Validate before calling

// Resolve exact plugin id from the server before toggling
List<PluginInfoVO> plugins = pluginClient.list("auth");
boolean exists = plugins.stream().anyMatch(p -> p.getPluginName().equals(name));
if (!exists) throw new IllegalArgumentException("unknown plugin auth:" + name);
pluginClient.setEnabled("auth", name, enabled, localOnly);

Try / catch

try {
    pluginClient.setEnabled(type, name, enabled, localOnly);
} catch (NacosApiException e) {
    if (e.getErrCode() == 20004 && e.getMessage().contains("Plugin not found")) {
        // refresh the plugin list and retry with the real id
    } else { throw e; }
}

Prevention

When it happens

Trigger: PUT /v3/console/plugin/status?pluginType=auth&pluginName=ldap for a plugin that is not installed/registered; a typo in the type or name; calling before startup plugin scanning finished.

Common situations: Plugin jar missing from the classpath/plugins dir; using a plugin name that differs from its registered id; the plugin type abbreviation is wrong (e.g. "authentication" instead of "auth").

Related errors


AI-assisted analysis of alibaba/nacos@9b989acdf1 (2026-08-14). Data as JSON: /api/errors/1172df38d874cd4f. Report an issue: GitHub.