gradle/gradle · error · InvalidUserCodeException
The closure provided is not valid as a rule for '%s'.
Error message
The closure provided is not valid as a rule for '%s'.
What it means
DefaultRuleActionAdapter.createFromClosure wraps any RuleActionValidationException raised while building a closure-based rule action into an InvalidUserCodeException: 'The closure provided is not valid as a rule for <context>'. The context string names the rule container/DSL where the closure was declared. The real reason is in the cause: typically a wrong first-parameter type or an input parameter of an unsupported type.
Source
Thrown at platforms/software/dependency-management/src/main/java/org/gradle/internal/rules/DefaultRuleActionAdapter.java:45
@SuppressWarnings("InlineFormatString")
private static final String INVALID_ACTION_ERROR = "The action provided is not valid as a rule for '%s'.";
@SuppressWarnings("InlineFormatString")
private static final String INVALID_RULE_SOURCE_ERROR = "The rule source provided does not provide a valid rule for '%s'.";
private final RuleActionValidator ruleActionValidator;
private final String context;
public DefaultRuleActionAdapter(RuleActionValidator ruleActionValidator, String context) {
this.ruleActionValidator = ruleActionValidator;
this.context = context;
}
@Override
public <T> RuleAction<? super T> createFromClosure(Class<T> subjectType, Closure<?> closure) {
try {
return ruleActionValidator.validate(new ClosureBackedRuleAction<>(subjectType, closure));
} catch (RuleActionValidationException e) {
throw new InvalidUserCodeException(String.format(INVALID_CLOSURE_ERROR, context), e);
}
}
@Override
public <T> RuleAction<? super T> createFromAction(Action<? super T> action) {
try {
return ruleActionValidator.validate(new NoInputsRuleAction<>(action));
} catch (RuleActionValidationException e) {
throw new InvalidUserCodeException(String.format(INVALID_ACTION_ERROR, context), e);
}
}
@Override
@Deprecated
public <T> RuleAction<? super T> createFromRuleSource(Class<T> subjectType, Object ruleSource) {
try {
return ruleActionValidator.validate(RuleSourceBackedRuleAction.create(ModelType.of(subjectType), ruleSource));
} catch (RuleActionValidationException e) {View on GitHub (pinned to 534f27719b)
Solutions
- Read the caused-by RuleActionValidationException in the stack trace to see the concrete signature problem
- Fix the closure's first parameter to match the rule subject type
- Restrict extra closure parameters to the input types allowed by that container (listed in the underlying validation message)
Defensive patterns
Strategy: try-catch
Try / catch
try {
adapter.createFromClosure(subjectType, closure)
} catch (org.gradle.api.InvalidUserCodeException e) {
def cause = e.cause
if (cause instanceof org.gradle.internal.rules.RuleActionValidationException) {
// fix the closure signature per cause.message
throw new GradleException('Invalid rule closure: ' + cause.message, e)
}
throw e
} Prevention
- Match closure first-parameter types to the rule subject before registering
- Check allowed input types for the container before adding extra parameters
- Always inspect the caused-by chain of InvalidUserCodeException from rule APIs
When it happens
Trigger: Adding a closure rule to a rule-based container (e.g. legacy native/software-model DSLs built on RuleActionAdapter) whose closure signature fails validation — bad subject parameter type (1247) or disallowed input parameter types (1251).
Common situations: Authoring or upgrading software-model-era build logic; migrating between Gradle versions where allowed rule input types changed; copy-pasting example closures into a different rule container.
Related errors
- The action provided is not valid as a rule for '%s'.
- First parameter of rule action closure must be of type '%s'.
- The rule source provided does not provide a valid rule for '
- Rule may not have an input parameter of type: %s.
- Direct instantiation of a BaseBinarySpec is not permitted. U
AI-assisted analysis of gradle/gradle@534f27719b (2026-08-22).
Data as JSON: /api/errors/8cedf464944c92e7.
Report an issue: GitHub.