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
}
    /**
     * Whether this plugin uses only stable APIs.
     */
    public boolean isStable() {
        return isStable;
    }
    @Override
    public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
        builder.startObject();
        toXContentFragment(builder, params);
        builder.endObject();
        return builder;
    }
    public XContentBuilder toXContentFragment(XContentBuilder builder, Params params) throws IOException {
        builder.field("name", name);
        builder.field("version", version);
        builder.field("elasticsearch_version", elasticsearchVersion);
        builder.field("java_version", javaVersion);
        builder.field("description", description);
        builder.field("classname", classname);
        builder.field("extended_plugins", extendedPlugins);
        builder.field("has_native_controller", hasNativeController);
        builder.field("licensed", isLicensed);
        return builder;
    }
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;