{"record":{"id":"a84b7325a30df6b2","repo":"gradle/gradle","slug":"an-artifact-transform-action-type-must-be-provided","errorCode":null,"errorMessage":"An artifact transform action type must be provided.","messagePattern":"An artifact transform action type must be provided\\.","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"platforms/software/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultVariantTransformRegistry.java","lineNumber":124,"sourceCode":"                formatter.append(\"from \");\n                formatter.appendValue(registration.from);\n            }\n            if (!registration.to.isEmpty()) {\n                if (!registration.from.isEmpty()) {\n                    formatter.append(\" \");\n                }\n                formatter.append(\"to \");\n                formatter.appendValue(registration.to);\n            }\n            formatter.append(\")\");\n        }\n        formatter.append(\".\");\n        return formatter.toString();\n    }\n\n    private <T> void validateActionType(@Nullable Class<T> actionType) {\n        if (actionType == null) {\n            throw new IllegalArgumentException(\"An artifact transform action type must be provided.\");\n        }\n    }\n\n    @NonExtensible\n    public static abstract class TypedRegistration<T extends TransformParameters> implements TransformSpec<T> {\n        private final AttributeContainerInternal from;\n        private final AttributeContainerInternal to;\n        private final T parameterObject;\n\n        @Inject\n        protected abstract DocumentationRegistry getDocumentationRegistry();\n\n        public TypedRegistration(T parameterObject, AttributesFactory attributesFactory) {\n            this.parameterObject = parameterObject;\n            this.from = attributesFactory.mutable();\n            this.to = attributesFactory.mutable();\n        }\n","sourceCodeStart":106,"sourceCodeEnd":142,"githubUrl":"https://github.com/gradle/gradle/blob/534f27719b66953f95cc907aae7f2c1b12f5482d/platforms/software/dependency-management/src/main/java/org/gradle/api/internal/artifacts/transform/DefaultVariantTransformRegistry.java#L106-L142","documentation":"registerTransform requires the Class of a TransformAction implementation; DefaultVariantTransformRegistry.validateActionType fails fast with this IllegalArgumentException when the action type argument is null, before any registration work starts. In practice null arrives from plugin/configuration code (an unset class property, a failed lookup) rather than a literal null literal in a build script.","triggerScenarios":"Calling dependencies.registerTransform(null) { ... }; passing a Class property from a plugin extension that was never set; resolving the class from a name-to-class map whose key is missing and handing the null result to registerTransform.","commonSituations":"Plugins that let users configure which transform class to apply and the user did not configure it; class-forName lookups with typos returning null; conditional registration code referencing an unset variable.","solutions":["Pass a concrete TransformAction class literal: dependencies.registerTransform(MinifyAction) { ... }","If the class comes from configuration or a lookup, null-check it and fail with your own descriptive message before calling registerTransform","Fix the lookup that produced null (typo in the class name or map key)"],"exampleFix":"// before\ndef actionClass = transformClassesByName[extension.transformName] // null: unknown name\ndependencies.registerTransform(actionClass) { it.to.attribute(ArtifactTypeDefinition.ARTIFACT_TYPE, 'min') }\n\n// after\ndef actionClass = transformClassesByName[extension.transformName]\n    ?: throw new GradleException(\"Unknown transform '${extension.transformName}'. Available: ${transformClassesByName.keySet()}\")\ndependencies.registerTransform(actionClass) { it.to.attribute(ArtifactTypeDefinition.ARTIFACT_TYPE, 'min') }","handlingStrategy":"validation","validationCode":"// before calling registerTransform with a dynamic class\ndef actionClass = transformClassesByName[name]\nif (actionClass == null) {\n    throw new GradleException(\"Unknown transform '${name}'. Available: ${transformClassesByName.keySet()}\")\n}","typeGuard":"// Java: narrow and validate the action class before registration\nstatic Class<? extends TransformAction<?>> asTransformAction(Class<?> c) {\n    Objects.requireNonNull(c, \"transform action class must not be null\");\n    if (!TransformAction.class.isAssignableFrom(c)) {\n        throw new IllegalArgumentException(c + \" does not implement TransformAction\");\n    }\n    return c.asSubclass(TransformAction.class);\n}","tryCatchPattern":null,"preventionTips":["Prefer class literals over name-based lookups when calling registerTransform","Fail with your own message when an optional transform class is not configured","Log which transform class is being registered in plugin debug output"],"tags":["gradle","artifact-transform","null-argument","api-misuse"],"backgroundTag":"missing-required-argument","analyzedSha":"534f27719b66953f95cc907aae7f2c1b12f5482d","analyzedAt":"2026-08-22T08:09:12.375Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}