gradle/gradle · warning

%s: Could not find plugin descriptor of %s at META-INF/gradl

Error message

%s: Could not find plugin descriptor of %s at META-INF/gradle-plugins/%s.properties

What it means

For every gradlePlugin.plugins declaration, validation expects a matching descriptor file named <id>.properties in META-INF/gradle-plugins inside the jar. DECLARED_PLUGIN_MISSING_MESSAGE fires when the declaration exists but no such file name was collected: the declaration and the jar contents are out of sync.

Source

Thrown at platforms/extensibility/plugin-development/src/main/java/org/gradle/plugin/devel/plugins/JavaGradlePluginPlugin.java:388

                        descriptorURI = descriptor.getPropertiesFileUrl().toURI();
                    } catch (URISyntaxException e) {
                        // Do nothing since the only side effect is that we wouldn't
                        // be able to log the plugin descriptor file name.  Shouldn't
                        // be a reasonable scenario where this occurs since these
                        // descriptors should be generated from real files.
                    }
                    String pluginFileName = descriptorURI != null ? new File(descriptorURI).getName() : "UNKNOWN";
                    pluginFileNames.add(pluginFileName);
                    String pluginImplementation = descriptor.getImplementationClassName();
                    if (pluginImplementation.length() == 0) {
                        LOGGER.warn(String.format(INVALID_DESCRIPTOR_WARNING_MESSAGE, task.getPath(), pluginFileName));
                    } else if (!hasFullyQualifiedClass(pluginImplementation)) {
                        LOGGER.warn(String.format(BAD_IMPL_CLASS_WARNING_MESSAGE, task.getPath(), pluginFileName, pluginImplementation));
                    }
                }
                for (PluginDeclaration declaration : plugins.get()) {
                    if (!pluginFileNames.contains(declaration.getId() + ".properties")) {
                        LOGGER.warn(String.format(DECLARED_PLUGIN_MISSING_MESSAGE, task.getPath(), declaration.getName(), declaration.getId()));
                    }
                }
            }
        }

        boolean hasFullyQualifiedClass(String fqClass) {
            return actionsState.getCollectedClasses().contains(fqClass.replaceAll("\\.", "/") + ".class");
        }
    }

    /**
     * A file copy action that collects plugin descriptors as they are added to the jar.
     */
    static class PluginDescriptorCollectorAction implements Action<FileCopyDetails> {
        private final PluginValidationActionsState actionsState;

        PluginDescriptorCollectorAction(PluginValidationActionsState actionsState) {
            this.actionsState = actionsState;

View on GitHub (pinned to 534f27719b)

Solutions

  1. Align the declaration id with the descriptor file name: id 'com.example.greeting' must produce META-INF/gradle-plugins/com.example.greeting.properties.
  2. Undo source-set or processResources customizations that exclude or relocate generated descriptors.
  3. Build the jar and list META-INF/gradle-plugins to see which files actually shipped.
  4. Re-run ./gradlew validatePlugins to confirm every declaration maps to a file.

Example fix

// before: declaration id does not match shipped descriptor
gradlePlugin {
    plugins {
        create('greeting') { id = 'com.example.greet' } // expects com.example.greet.properties
    }
}
// jar contains META-INF/gradle-plugins/com.example.greeting.properties

// after: make them match
create('greeting') { id = 'com.example.greeting' }
Defensive patterns

Strategy: validation

Validate before calling

tasks.register('checkDescriptorIds') {
    dependsOn jar
    doLast {
        new ZipFile(jar.archiveFile.get().asFile).withCloseable { zf ->
            gradlePlugin.plugins.each { d ->
                def entry = "META-INF/gradle-plugins/${d.id}.properties"
                if (zf.getEntry(entry) == null) {
                    throw new GradleException("declaration ${d.id} has no ${entry} in jar")
                }
            }
        }
    }
}

Prevention

When it happens

Trigger: Declaring a plugin with an id while descriptor generation or placement was customized away (processResources/source set changes), the id in the declaration not matching the generated file name, or resources re-routed so the .properties never lands in the jar.

Common situations: Custom processResources or sourceSets configuration breaking descriptor generation; renaming plugin ids without regenerating descriptors; disabling the generate-plugin-descriptors output.

Related errors


AI-assisted analysis of gradle/gradle@534f27719b (2026-08-22). Data as JSON: /api/errors/336c3e43e8627c98. Report an issue: GitHub.