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/PluginDescriptorTests.java
name,
            "foo",
            "dummy",
            Version.CURRENT,
            "1.8",
            "dummyclass",
            null,
            List.of(),
            randomBoolean(),
            randomBoolean(),
            randomBoolean(),
            randomBoolean()
        );
    }
    public void testPluginListSorted() {
        List<PluginRuntimeInfo> plugins = new ArrayList<>();
        plugins.add(new PluginRuntimeInfo(newMockDescriptor("c")));
        plugins.add(new PluginRuntimeInfo(newMockDescriptor("b")));
        plugins.add(new PluginRuntimeInfo(newMockDescriptor("e")));
        plugins.add(new PluginRuntimeInfo(newMockDescriptor("a")));
        plugins.add(new PluginRuntimeInfo(newMockDescriptor("d")));
        PluginsAndModules pluginsInfo = new PluginsAndModules(plugins, Collections.emptyList());
        final List<PluginRuntimeInfo> infos = pluginsInfo.getPluginInfos();
        List<String> names = infos.stream().map(p -> p.descriptor().getName()).toList();
        assertThat(names, contains("a", "b", "c", "d", "e"));
    }
    public void testUnknownProperties() throws Exception {
        assertBothDescriptors(writer -> {
            IllegalArgumentException e = expectThrows(IllegalArgumentException.class, () -> writer.write("extra", "property"));
            assertThat(e.getMessage(), containsString("Unknown properties for plugin [my_plugin] in plugin descriptor"));