We pass `null` for the class name here:

https://github.com/elastic/elasticsearch/blob/f086dd18ddc705bf84a1ff99d35196ec2498fd52/server/src/main/java/org/elasticsearch/plugins/PluginDescriptor.java#L261

However the class name is mandatory for the transport protocol today:

https://github.com/elastic/elasticsearch/blob/f086dd18ddc705bf84a1ff99d35196ec2498fd52/server/src/main/java/org/elasticsearch/plugins/PluginDescriptor.java#L156

This prevents various APIs from working in a cluster with stable plugins installed.
server/src/main/java/org/elasticsearch/plugins/PluginDescriptor.java
this.moduleName = null;
        }
        extendedPlugins = in.readStringCollectionAsList();
        hasNativeController = in.readBoolean();
        if (in.getTransportVersion().onOrAfter(LICENSED_PLUGINS_SUPPORT)) {
            if (in.getTransportVersion().before(BOOTSTRAP_SUPPORT_REMOVED)) {
                in.readString(); 
                in.readOptionalString(); 
            }
            isLicensed = in.readBoolean();
        } else {
            isLicensed = false;
        }
        if (in.getTransportVersion().onOrAfter(TransportVersions.V_8_4_0)) {
            isModular = in.readBoolean();
            isStable = in.readBoolean();
        } else {
            isModular = moduleName != null;
            isStable = false;
        }
    }
    @Override
    public void writeTo(final StreamOutput out) throws IOException {
        out.writeString(name);
        out.writeString(description);
        out.writeString(version);
        Version.writeVersion(elasticsearchVersion, out);
        out.writeString(javaVersion);
        out.writeString(classname);
        if (out.getTransportVersion().onOrAfter(MODULE_NAME_SUPPORT)) {