{"record":{"id":"5ffba1c03916537c","repo":"gradle/gradle","slug":"a-s-needs-to-be-specified-for-the-s","errorCode":null,"errorMessage":"A %s needs to be specified for the %s.","messagePattern":"A (.+?) needs to be specified for the (.+?)\\.","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"platforms/native/language-native/src/main/java/org/gradle/language/nativeplatform/internal/Dimensions.java","lineNumber":110,"sourceCode":"                                           AttributesFactory attributesFactory,\n                                           Provider<String> group, Provider<String> version,\n                                           Action<NativeVariantIdentity> action) {\n        Collection<BuildType> buildTypes = BuildType.DEFAULT_BUILD_TYPES;\n        Collection<Linkage> linkages = extractAndValidate(\"linkage\", \"library\", declaredLinkages);\n        Collection<TargetMachine> targetMachines = extractAndValidate(\"target machine\", \"library\", declaredTargetMachines);\n        variants(baseName, buildTypes, linkages, targetMachines, attributesFactory, group, version, action);\n    }\n\n    private static <T> Collection<T> extractAndValidate(String propertyName, String componentName, SetProperty<T> declared) {\n        declared.finalizeValue();\n        Collection<T> value = declared.get();\n        assertNonEmpty(propertyName, componentName, value);\n        return value;\n    }\n\n    private static void assertNonEmpty(String propertyName, String componentName, Collection<?> property) {\n        if (property.isEmpty()) {\n            throw new IllegalArgumentException(String.format(\"A %s needs to be specified for the %s.\", propertyName, componentName));\n        }\n    }\n\n    private static void validateTargetMachines(Collection<TargetMachine> testTargetMachines, Collection<TargetMachine> mainTargetMachines) {\n        for (TargetMachine machine : testTargetMachines) {\n            if (!mainTargetMachines.contains(machine)) {\n                throw new IllegalArgumentException(\"The target machine \" + machine.toString() + \" was specified for the unit test, but this target machine was not specified on the component under test.\");\n            }\n        }\n    }\n\n    private static void variants(Provider<String> baseName, Collection<BuildType> buildTypes, Collection<Linkage> linkages, Collection<TargetMachine> targetMachines,\n                                 AttributesFactory attributesFactory,\n                                 // TODO: These should come from somewhere else, probably\n                                 Provider<String> group, Provider<String> version,\n                                 Action<NativeVariantIdentity> action) {\n        for (BuildType buildType : buildTypes) {\n            for (Linkage linkage : linkages) {","sourceCodeStart":92,"sourceCodeEnd":128,"githubUrl":"https://github.com/gradle/gradle/blob/534f27719b66953f95cc907aae7f2c1b12f5482d/platforms/native/language-native/src/main/java/org/gradle/language/nativeplatform/internal/Dimensions.java#L92-L128","documentation":"Dimensions.extractAndValidate() finalizes a component's declared dimension sets (buildTypes, linkages, targetMachines) and assertNonEmpty throws IllegalArgumentException 'A <propertyName> needs to be specified for the <componentName>.' when a set is empty - variant calculation requires at least one value on every dimension.","triggerScenarios":"Clearing or never populating a dimension on a native component before binaries are calculated: e.g. library.targetMachines = [] in build.gradle, an empty buildTypes = [] set, or linkages = [] - the failure fires when the plugin computes variants for the component.","commonSituations":"Trying to 'disable' a library by emptying its target machines or linkages; assigning targetMachines = [ ] instead of targetMachines.set([host()]) by mistake; a plugin computing per-component dimensions from an empty config list.","solutions":["Keep at least one value per dimension: e.g. targetMachines = [machines.host()] or machines.windows.x86_64 instead of an empty list.","If the intent was to disable building, don't empty a dimension - remove/avoid applying the component or its publish/plugin instead.","Validate the sets in your own configuration code right after assignment so the error surfaces with your own context."],"exampleFix":"// before: empty dimension -> IllegalArgumentException when variants are calculated\nlibrary.targetMachines = []\n\n// after: explicit single target\nlibrary.targetMachines = [machines.host()]","handlingStrategy":"validation","validationCode":"// Validate dimensions right after configuring the component:\nassert !library.targetMachines.empty : 'targetMachines must not be empty'\nassert !library.buildTypes.empty : 'buildTypes must not be empty'\n// or set explicit values instead of clearing:\nlibrary.targetMachines = [machines.host()]","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never 'disable' a native component by emptying a dimension set","Set at least one build type, linkage, and target machine for every component","Prefer explicit values ([machines.host()]) over relying on defaults you then override with empty lists"],"tags":["gradle","native","dimensions","target-machines","validation","illegal-argument"],"backgroundTag":"missing-required-build-dimension","analyzedSha":"534f27719b66953f95cc907aae7f2c1b12f5482d","analyzedAt":"2026-08-22T08:09:12.375Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}