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/test/java/org/elasticsearch/plugins/PluginsServiceTests.java
extensions = loader.loadExtensions(TestExtensionPoint.class);
            
            expectThrows(UnsupportedOperationException.class, () -> extensions.add(new TestExtension1()));
        }
    }
    public static class TestPlugin extends Plugin {}
    public interface TestExtensionPoint {}
    public static class TestExtension1 implements TestExtensionPoint {}
    public static class TestExtension2 implements TestExtensionPoint {
        public Plugin plugin;
        public TestExtension2(TestPlugin plugin) {
            this.plugin = plugin;
        }
    }
    public static class BadSingleParameterConstructorExtension implements TestExtensionPoint {
        public BadSingleParameterConstructorExtension(String bad) {}
    }
    public static class TooManyParametersConstructorExtension implements TestExtensionPoint {
        public TooManyParametersConstructorExtension(String bad) {}
    }
    public static class ThrowingConstructorExtension implements TestExtensionPoint {
        public ThrowingConstructorExtension() {
            throw new IllegalArgumentException("test constructor failure");
        }
    }
    public static class PluginOther extends Plugin {
        public PluginOther() {}
    }
}