junit-team/junit5 · error · PreconditionViolationException
Filter [%s] must implement %s, %s, or %s.
Error message
Filter [%s] must implement %s, %s, or %s.
What it means
Thrown by LauncherDiscoveryRequestBuilder.storeFilter() when a Filter passed to .filters(Filter<?>...) is neither an EngineFilter, a PostDiscoveryFilter, nor a DiscoveryFilter. The builder classifies each filter by instanceof and rejects unknown filter types with PreconditionViolationException naming the offending object and the three accepted interfaces.
Source
Thrown at junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/LauncherDiscoveryRequestBuilder.java:369
@API(status = MAINTAINED, since = "1.14")
public LauncherDiscoveryRequestBuilder outputDirectoryCreator(OutputDirectoryCreator outputDirectoryCreator) {
this.outputDirectoryCreator = Preconditions.notNull(outputDirectoryCreator,
"outputDirectoryCreator must not be null");
return this;
}
private void storeFilter(Filter<?> filter) {
if (filter instanceof EngineFilter engineFilter) {
this.engineFilters.add(engineFilter);
}
else if (filter instanceof PostDiscoveryFilter postDiscoveryFilter) {
this.postDiscoveryFilters.add(postDiscoveryFilter);
}
else if (filter instanceof DiscoveryFilter<?> discoveryFilter) {
this.discoveryFilters.add(discoveryFilter);
}
else {
throw new PreconditionViolationException(
"Filter [%s] must implement %s, %s, or %s.".formatted(filter, EngineFilter.class.getSimpleName(),
PostDiscoveryFilter.class.getSimpleName(), DiscoveryFilter.class.getSimpleName()));
}
}
/**
* Builds this discovery request and returns a new builder for creating a
* {@link org.junit.platform.launcher.LauncherExecutionRequest} that is
* initialized to contain the resulting discovery request.
*
* @return a new {@link LauncherExecutionRequestBuilder}
* @since 6.0
*/
@API(status = EXPERIMENTAL, since = "6.0")
public LauncherExecutionRequestBuilder forExecution() {
return LauncherExecutionRequestBuilder.request(build());
}
View on GitHub (pinned to 956246301e)
Solutions
- Ensure every filter passed implements EngineFilter, PostDiscoveryFilter, or DiscoveryFilter.
- Use the documented factory methods (includeEngines, includeTags, includeClassNamePatterns) which return the correct subtypes.
- If you have a custom filter, implement PostDiscoveryFilter (most common choice) or DiscoveryFilter.
Example fix
// before
.filters(new MyRawFilter()) // MyRawFilter only implements Filter<TestDescriptor>
// after
public class MyRawFilter implements PostDiscoveryFilter { ... }
.filters(new MyRawFilter()) Defensive patterns
Strategy: type-guard
Validate before calling
import org.junit.platform.launcher.EngineFilter;
import org.junit.platform.launcher.PostDiscoveryFilter;
import org.junit.platform.engine.DiscoveryFilter;
for (Filter<?> f : filters) {
if (!(f instanceof EngineFilter || f instanceof PostDiscoveryFilter || f instanceof DiscoveryFilter)) {
throw new IllegalArgumentException("Unsupported filter: " + f.getClass());
}
} Type guard
static boolean isAcceptableFilter(Filter<?> f) {
return f instanceof EngineFilter
|| f instanceof PostDiscoveryFilter
|| f instanceof DiscoveryFilter;
} Prevention
- Use the documented factory methods (includeEngines, includeTags, includeClassNamePatterns) which return correct subtypes.
- Make custom filters implement PostDiscoveryFilter or DiscoveryFilter.
- Unit-test filter wiring against the builder before integration runs.
When it happens
Trigger: Passing a raw Filter implementation, a tag filter wrapped incorrectly, or any custom Filter that does not extend one of the three recognised interfaces into LauncherDiscoveryRequestBuilder.filters(...).
Common situations: Passing TagFilter.includeTags(...) correctly is fine (it returns a PostDiscoveryFilter), but passing a hand-rolled Filter or a ClassNameFilter where the static import returns a DiscoveryFilter (which is accepted) vs a plain Filter. Mixing in a org.junit.platform.engine.Filter subtype that is none of the three. Wrong static import returning a generic Filter.
Related errors
- '%s' is not a well-formed UniqueId segment
- Could not find any resource(s) with name: ${this.classpathRe
- Failed to create a java.net.URI from: ${uri}
- Failed to retrieve canonical path for file: ${file}
- Failed to retrieve canonical path for directory: ${directory
AI-assisted analysis of junit-team/junit5@956246301e (2026-08-04).
Data as JSON: /data/errors/aae64ee5e85187f6.json.
Report an issue: GitHub.