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
Files.createDirectories(fake);
        Files.createFile(fake.resolve("plugin.jar"));
        final Path removing = home.resolve("plugins").resolve(".removing-fake");
        Files.createFile(removing);
        PluginTestUtil.writePluginProperties(
            fake,
            "description",
            "fake",
            "name",
            "fake",
            "version",
            "1.0.0",
            "elasticsearch.version",
            Version.CURRENT.toString(),
            "java.version",
            System.getProperty("java.specification.version"),
            "classname",
            "Fake",
            "has.native.controller",
            "false"
        );
        final IllegalStateException e = expectThrows(IllegalStateException.class, () -> newPluginsService(settings));
        final String expected = Strings.format(
            "found file [%s] from a failed attempt to remove the plugin [fake]; execute [elasticsearch-plugin remove fake]",
            removing
        );
        assertThat(e, hasToString(containsString(expected)));
    }
    public void testLoadPluginWithNoPublicConstructor() {
        class NoPublicConstructorPlugin extends Plugin {