gradle/gradle · error · MetaDataParseException

inconsistent module metadata found. Descriptor: %s Errors: %

Error message

inconsistent module metadata found. Descriptor: %s Errors: %s

What it means

Thrown when Gradle parses a fetched module descriptor (POM, Ivy XML or Gradle .module file) and the group/module/version declared inside the descriptor do not match the coordinates that were requested. AbstractRepositoryMetadataSource.checkMetadataConsistency compares each part and collects every mismatch ('bad group/module name/version: expected vs found') into one MetaDataParseException. It exists to stop the dependency graph from accepting an artifact published under wrong coordinates.

Source

Thrown at platforms/software/dependency-management/src/main/java/org/gradle/api/internal/artifacts/repositories/metadata/AbstractRepositoryMetadataSource.java:126

        return sha1;
    }

    private ModuleDescriptorArtifactMetadata getMetaDataArtifactFor(ModuleComponentIdentifier moduleComponentIdentifier) {
        IvyArtifactName ivyArtifactName = metadataArtifactProvider.getMetaDataArtifactName(moduleComponentIdentifier.getModule());
        return new DefaultModuleDescriptorArtifactMetadata(moduleComponentIdentifier, ivyArtifactName);
    }

    void checkMetadataConsistency(ModuleComponentIdentifier expectedId, MutableModuleComponentResolveMetadata metadata) throws MetaDataParseException {
        checkModuleIdentifier(expectedId, metadata.getModuleVersionId());
    }

    private void checkModuleIdentifier(ModuleComponentIdentifier expectedId, ModuleVersionIdentifier actualId) {
        List<String> errors = new ArrayList<>();
        checkEquals("group", expectedId.getGroup(), actualId.getGroup(), errors);
        checkEquals("module name", expectedId.getModule(), actualId.getName(), errors);
        checkEquals("version", expectedId.getVersion(), actualId.getVersion(), errors);
        if (errors.size() > 0) {
            throw new MetaDataParseException(
                    String.format("inconsistent module metadata found. Descriptor: %s Errors: %s", actualId, joinLines(errors)));
        }
    }

    private String joinLines(List<String> lines) {
        return Joiner.on(SystemProperties.getInstance().getLineSeparator()).join(lines);
    }

    private void checkEquals(String label, String expected, String actual, List<String> errors) {
        if (!expected.equals(actual)) {
            errors.add("bad " + label + ": expected='" + expected + "' found='" + actual + "'");
        }
    }

    protected abstract MetaDataParser.ParseResult<S> parseMetaDataFromResource(ModuleComponentIdentifier moduleComponentIdentifier, LocallyAvailableExternalResource cachedResource, ExternalResourceArtifactResolver artifactResolver, DescriptorParseContext context, String repoName);

}

View on GitHub (pinned to 534f27719b)

Solutions

  1. Read the 'bad group/module name/version: expected ... found ...' lines in the message, then fix the publishing side so the descriptor matches the coordinates it is published under.
  2. If publishing is not under your control, change the dependency to the coordinates actually declared in the descriptor, or use dependency substitution / a component metadata rule to remap the module.
  3. Verify that a mirror, proxy or repository content filtering is not serving the wrong artifact for the requested module path.
  4. Check for accidental duplicate dependencies on both the old and relocated coordinates with conflicting versions.

Example fix

// before: depending on stale coordinates that the descriptor no longer matches
implementation 'com.example:foo:1.0'
// after: depend on the coordinates the descriptor actually declares (or fix the publisher)
implementation 'com.example:newgroup:foo:1.0'
Defensive patterns

Strategy: try-catch

Validate before calling

def pom = new XmlSlurper().parseText(pomFile.text)
def actual = "${pom.groupId.text()}:${pom.artifactId.text()}:${pom.version.text()}"
assert actual == requestedCoordinates : "descriptor declares $actual, requested $requestedCoordinates"

Try / catch

try {
  def files = config.resolvedConfiguration.lenientConfiguration
} catch (Exception e) {
  def cause = walkCauses(e).find { it.class.simpleName == 'MetaDataParseException' }
  if (cause) { /* message lists bad group/module/version: fix publishing or remap dependency */ }
  throw e
}

Prevention

When it happens

Trigger: Resolving a module whose descriptor declares different coordinates than requested, e.g. requesting 'com.example:foo:1.0' when the POM says groupId 'com.example.bar'; a Maven relocation published incorrectly; a repository/mirror/content-filter that serves the wrong file for the requested module path.

Common situations: A library was renamed or moved but republished with stale descriptor coordinates; corporate proxy or repository filtering rule returning a different module; broken generatePom configuration on the publishing side; SNAPSHOT metadata drift.

Related errors


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