elastic/elasticsearch · error · GradleException

Sysprop [ ] must be [true] or [false] but was [ ]

Error message

Sysprop [${property}] must be [true] or [false] but was [${propertyValue}]

What it means

Util.getBooleanProperty reads a Java system property and only accepts the canonical strings "true" and "false"; unset falls back to the default. Anything else — yes, no, 1, 0, TRUE, empty — throws a GradleException naming the property and the bad value. This guards build switches against silent truthy/falsy coercion.

Solutions

  1. Set the property to exactly true or false.
  2. Leave it unset to take the default.
  3. Fix the upstream env-to-sysprop mapping to canonicalise before passing to Gradle.

Example fix

// before
./gradlew build -Dtests.leaks=1
// after
./gradlew build -Dtests.leaks=true
Defensive patterns

Strategy: validation

Validate before calling

static boolean canonicalBoolean(String property, boolean defaultValue) {
    String v = System.getProperty(property);
    if (v == null) return defaultValue;
    if ("true".equals(v)) return true;
    if ("false".equals(v)) return false;
    throw new GradleException("Sysprop [" + property + "] must be [true] or [false] but was [" + v + "]");
}

Type guard

static boolean isCanonicalBoolean(String s) {
    return "true".equals(s) || "false".equals(s);
}

Prevention

When it happens

Trigger: Calling Util.getBooleanProperty(name, default) while -D<name> is set to a non-canonical boolean string. Common call sites in this repo read feature-flag and behaviour sysprops during configuration.

Common situations: A CI matrix exporting booleans as 1/0 or yes/no that get mapped verbatim onto the sysprop; a wrapper script uppercasing values; a user passing -Dfoo=True expecting case-insensitivity.

Related errors


AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12). Data as JSON: /api/errors/79dd8fb2d05c4dd0. Report an issue: GitHub.

Appendix: source

Thrown at build-conventions/src/main/java/org/elasticsearch/gradle/internal/conventions/util/Util.java:42

import java.io.File;
import java.util.Optional;
import java.util.function.Supplier;

import javax.annotation.Nullable;

public class Util {

    public static boolean getBooleanProperty(String property, boolean defaultValue) {
        String propertyValue = System.getProperty(property);
        if (propertyValue == null) {
            return defaultValue;
        }
        if ("true".equals(propertyValue)) {
            return true;
        } else if ("false".equals(propertyValue)) {
            return false;
        } else {
            throw new GradleException("Sysprop [" + property + "] must be [true] or [false] but was [" + propertyValue + "]");
        }
    }

    /**
     * @param project The project to look for resources.
     * @param filter  Optional filter function to filter the returned resources
     * @return Returns the {@link FileTree} for main resources from Java projects. Returns null if no files exist.
     */
    @Nullable
    public static FileTree getJavaMainSourceResources(Project project, Action<? super PatternFilterable> filter) {
        final Optional<FileTree> mainFileTree = getJavaMainSourceSet(project).map(SourceSet::getResources).map(FileTree::getAsFileTree);
        return mainFileTree.map(files -> files.matching(filter)).orElse(null);
    }

    /**
     * @param project The project to look for resources.
     * @param filter  Optional filter function to filter the returned resources
     * @return Returns the {@link FileTree} for test resources from Java projects. Returns null if no files exist.

View on GitHub (pinned to db6a809a66)