Custom archive causes NPE inside Ivy's AbstractArtifact with 1.11

def theFile = new File(buildDir, 'foo.txt')
task buildTheFile << {
  theFile << "bar"
}
tasks.findByName('assemble').dependsOn buildTheFile
   artifacts {
  archives file: theFile, name: 'my-artifact', type: 'text', builtBy: buildTheFile
}
Caused by: java.lang.NullPointerException
 at org.apache.ivy.core.module.descriptor.AbstractArtifact.hashCode(AbstractArtifact.java:51)
 at org.apache.ivy.core.module.descriptor.DefaultModuleDescriptor.addArtifact(DefaultModuleDescriptor.java:375)
 at org.gradle.api.internal.artifacts.metadata.DefaultLocalComponentMetaData.addArtifact(DefaultLocalComponentMetaData.java:53)
 at org.gradle.api.internal.artifacts.ivyservice.moduleconverter.DefaultConfigurationsToArtifactsConverter.addArtifacts(DefaultConfigurationsToArtifactsConverter.java:38)
 at org.gradle.api.internal.artifacts.ivyservice.moduleconverter.PublishLocalComponentFactory.convert(PublishLocalComponentFactory.java:44)
 at org.gradle.api.internal.artifacts.ivyservice.projectmodule.ProjectDependencyResolver.resolve(ProjectDependencyResolver.java:53)
 at org.gradle.api.internal.artifacts.ivyservice.resolveengine.DependencyGraphBuilder.resolve(DependencyGraphBuilder.java:64)
 at org.gradle.api.internal.artifacts.ivyservice.resolveengine.DefaultDependencyResolver$1.transform(DefaultDependencyResolver.java:108)
 at org.gradle.api.internal.artifacts.ivyservice.resolveengine.DefaultDependencyResolver$1.transform(DefaultDependencyResolver.java:77)
 at org.gradle.api.internal.artifacts.ivyservice.DefaultIvyContextManager.withIvy(DefaultIvyContextManager.java:61)
 at org.gradle.api.internal.artifacts.ivyservice.resolveengine.DefaultDependencyResolver.resolve(DefaultDependencyResolver.java:77)
 at org.gradle.api.internal.artifacts.ivyservice.CacheLockingArtifactDependencyResolver$1.create(CacheLockingArtifactDependencyResolver.java:39)
 at org.gradle.api.internal.artifacts.ivyservice.CacheLockingArtifactDependencyResolver$1.create(CacheLockingArtifactDependencyResolver.java:37)
 at org.gradle.cache.internal.DefaultCacheAccess.useCache(DefaultCacheAccess.java:187)
 at org.gradle.cache.internal.DefaultPersistentDirectoryStore.useCache(DefaultPersistentDirectoryStore.java:102)
 at org.gradle.cache.internal.DefaultCacheFactory$ReferenceTrackingCache.useCache(DefaultCacheFactory.java:189)
 at org.gradle.api.internal.artifacts.ivyservice.DefaultCacheLockingManager.useCache(DefaultCacheLockingManager.java:61)
 at org.gradle.api.internal.artifacts.ivyservice.CacheLockingArtifactDependencyResolver.resolve(CacheLockingArtifactDependencyResolver.java:37)
 at org.gradle.api.internal.artifacts.ivyservice.SelfResolvingDependencyResolver.resolve(SelfResolvingDependencyResolver.java:41)
 at org.gradle.api.internal.artifacts.ivyservice.ShortcircuitEmptyConfigsArtifactDependencyResolver.resolve(ShortcircuitEmptyConfigsArtifactDependencyResolver.java:51)
 at org.gradle.api.internal.artifacts.ivyservice.ErrorHandlingArtifactDependencyResolver.resolve(ErrorHandlingArtifactDependencyResolver.java:44)
 at org.gradle.api.internal.artifacts.ivyservice.DefaultConfigurationResolver.resolve(DefaultConfigurationResolver.java:42)
 at org.gradle.api.internal.artifacts.configurations.DefaultConfiguration.resolveNow(DefaultConfiguration.java:240)
 at org.gradle.api.internal.artifacts.configurations.DefaultConfiguration.getResolvedConfiguration(DefaultConfiguration.java:230)
 at org.gradle.api.internal.artifacts.configurations.DefaultConfiguration_Decorated.getResolvedConfiguration(Unknown Source)
 at org.gradle.api.internal.artifacts.configurations.DefaultConfiguration$ConfigurationFileCollection.getFiles(DefaultConfiguration.java:463)
 ... 61 more

You’re missing the ‘ext’ (extension) property.

Ah, ok. I think this doc (specifically 15.4) needs updated then: http://www.gradle.org/docs/current/userguide/artifact_management.html

If you let me know it works, I’ll update the doc :slight_smile:

Actually, taking a deeper look… this is only required if the file you are adding doesn’t have an extension. If it does that is used as the default value.

My file lacks an extension. I’m guilty of doctoring my example code. Trying to add extension property now…

Success with:

artifacts {
  archives file: execFile, name: 'my-artifact', type: 'text', builtBy: execJar, extension: 'jar'
}

Thanks!

Great.

So this indicates that ‘ext’ is required even if ‘execFile’ has an extension?

My real file did not have an extension and required the ‘extension’ property. When I add an extension to the real file the additional property is not required.

The exception message kind of sucks but it’s down in Ivy. Should I file a request for a better message there?

Looks like it’s already been fixed in 1.12: https://github.com/gradle/gradle/commit/c21446f6ea7a32555d0e7f4fa89a8746cf995c0e