gradle/gradle · error · InvalidIvyPublicationException

supplied %s does not match ivy descriptor (cannot edit %1$s

Error message

supplied %s does not match ivy descriptor (cannot edit %1$s directly in the ivy descriptor file).

What it means

Before upload, ValidatingIvyPublisher re-parses the generated ivy.xml and compares its identity fields (organisation, module name, revision) with the publication coordinates. IvyFieldValidator.matches throws this when a field differs: identity fields cannot be changed by editing the ivy descriptor file.

Source

Thrown at platforms/software/ivy/src/main/java/org/gradle/api/publish/ivy/internal/publisher/ValidatingIvyPublisher.java:160

    private void checkCanPublish(String name, IvyArtifact artifact) {
        File artifactFile = artifact.getFile();
        if (artifactFile.isDirectory()) {
            throw new InvalidIvyPublicationException(name, String.format("artifact file is a directory: '%s'", artifactFile));
        }
    }

    private IvyFieldValidator field(IvyNormalizedPublication publication, String name, String value) {
        return new IvyFieldValidator(publication.getName(), name, value);
    }

    private static class IvyFieldValidator extends PublicationFieldValidator<IvyFieldValidator> {
        private IvyFieldValidator(String publicationName, String name, String value) {
            super(IvyFieldValidator.class, publicationName, name, value);
        }

        public IvyFieldValidator matches(String expectedValue) {
            if (!value.equals(expectedValue)) {
                throw new InvalidIvyPublicationException(publicationName,
                        String.format("supplied %s does not match ivy descriptor (cannot edit %1$s directly in the ivy descriptor file).", name)
                );
            }
            return this;
        }

        @Override
        protected InvalidUserDataException failure(String message) {
            throw new InvalidIvyPublicationException(publicationName, message);
        }
    }
}

View on GitHub (pinned to 534f27719b)

Solutions

  1. Set organisation/module/revision on the IvyPublication itself, never via withXml
  2. Delete the stale descriptor and regenerate: ./gradlew clean generateDescriptorFileForIvyPublication
  3. Remove any withXml block that rewrites <info> identity and mirror the change on publication properties

Example fix

// before
publication.descriptor.withXml {
    asNode().info[0].'@organisation' = 'com.correct' // rejected at publish time
}

// after
publication.organisation = 'com.correct'
Defensive patterns

Strategy: validation

Validate before calling

gradle.taskGraph.whenReady { graph ->
    def pub = publishing.publications.findByName('ivy')
    if (pub != null && graph.hasTask(pub.publishTasks.first())) {
        assert pub.organisation == project.group : 'publication organisation drifted from project.group'
        assert pub.revision == project.version.toString() : 'publication revision drifted from project.version'
    }
}

Prevention

When it happens

Trigger: publication.descriptor.withXml rewriting the <info> organisation/module/revision attributes; changing publication.organisation/version after the descriptor was generated; a stale ivy.xml left in the build directory from an earlier configuration; hand-editing the generated descriptor between generation and publish.

Common situations: Scripts that patch descriptor identity via withXml instead of setting publication properties; CI reusing a dirty build directory after changing project version or coordinates; plugins that rewrite ivy.xml metadata.

Related errors


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