gradle/gradle · error · IllegalArgumentException
Cannot convert '%s' to %s.
Error message
Cannot convert '%s' to %s.
What it means
ConfigurationPublications lazily creates the variants container guarded by beforeCollectionChanges: once the configuration has been observed (resolved or consumed during task-graph building), adding secondary artifact sets via outgoing.variants { } throws InvalidUserCodeException naming the configuration and the observation reason.
Source
Thrown at platforms/core-configuration/file-collections/src/main/java/org/gradle/api/internal/file/AbstractFileResolver.java:96
public String resolveForDisplay(Object path) {
return resolveAsRelativePath(path);
}
@Override
public File resolve(Object path, PathValidation validation) {
File maybeRelativeFile = unpackAndParseNotation(path, fileNotationParser, "File");
return resolveFile(maybeRelativeFile, validation);
}
@Override
public URI resolveUri(Object uri) {
return unpackAndParseNotation(uri, uriOrFileNotationParser, "URI");
}
private static <T> T unpackAndParseNotation(Object input, NotationParser<Object, T> parser, String hint) {
Object unpacked = DeferredUtil.unpack(input);
if (unpacked == null || "".equals(unpacked)) {
throw new IllegalArgumentException(String.format("Cannot convert '%s' to %s.", input, hint));
}
return parser.parseNotation(unpacked);
}
protected abstract File doResolve(File path);
private File resolveFile(File maybeRelativeFile, PathValidation validation) {
File file = doResolve(maybeRelativeFile);
file = FileUtils.normalize(file);
validate(file, validation);
return file;
}
protected void validate(File file, PathValidation validation) {
switch (validation) {
case NONE:
break;
case EXISTS:View on GitHub (pinned to 534f27719b)
Solutions
- Register all variants eagerly during plugin application, before anything can resolve the configuration
- Eliminate early resolution/consumption of the outgoing configuration
- If late registration seems required, add a new consumable configuration instead of a late variant
Example fix
// before
afterEvaluate {
configurations.myLib.outgoing.variants { // configuration already observed
documentation { artifact(javadocJar) }
}
}
// after
configurations.myLib.outgoing.variants { // during apply, before observation
documentation { artifact(javadocJar) }
} Defensive patterns
Strategy: validation
Validate before calling
if (conf.state != Configuration.State.UNRESOLVED) {
throw new GradleException("${conf.name} was observed; register variants earlier")
}
conf.outgoing.variants { register('docs') { artifact(javadocJar) } } Prevention
- Register variants during plugin apply, never in afterEvaluate
- Prevent early resolution of outgoing configurations
- Use one consumable configuration per variant set to avoid late additions
When it happens
Trigger: configurations.myOutgoing.outgoing.variants { register('extra') { artifact(file) } } executed after the configuration was resolved or its file collection consumed (task graph built, incoming.files read).
Common situations: Plugins registering additional variants in afterEvaluate or reactively after something already resolved the configuration; ordering conflicts between publishing plugins and early-resolving plugins.
Related errors
- File '%s' does not exist.
- Not implemented yet.
- Gradle Module Metadata for module {} is invalid because it d
- Variant '%s' doesn't belong to resolved component '%s'. %s M
- Classifier and artifact types aren't supported by dependency
AI-assisted analysis of gradle/gradle@534f27719b (2026-08-22).
Data as JSON: /api/errors/b0959c938b434ee0.
Report an issue: GitHub.