apache/seatunnel · error · org.apache.seatunnel.api.configuration.util.OptionValidationException
Condition for option '%s' has a null operator
Error message
Condition for option '%s' has a null operator
What it means
FileDiscoveryScanner.scan walks candidate directories and lists their contents; when the per-directory listing (e.g. session.listStatus) throws IOException, scan rethrows it wrapped as "Failed during source_listing for protocol=..., path=..." with the directory path masked and the original exception as cause. Unlike the root_stat error, this happens after the root was successfully statted, i.e. during traversal of a subdirectory.
Source
Thrown at seatunnel-api/src/main/java/org/apache/seatunnel/api/configuration/util/ConditionEvaluators.java:46
import java.util.Objects;
/**
* Registry of per-{@link ConditionOperator} evaluation logic. Stateless; every evaluator is a pure
* function of (value, condition, config).
*/
public final class ConditionEvaluators {
@FunctionalInterface
interface Evaluator {
boolean evaluate(Object value, Condition<?> condition, ReadonlyConfig config);
}
private static final Map<ConditionOperator, Evaluator> REGISTRY = createRegistry();
static boolean evaluate(Condition<?> condition, ReadonlyConfig config) {
ConditionOperator operator = condition.getOperator();
if (operator == null) {
throw new OptionValidationException(
"Condition for option '%s' has a null operator", condition.getOption().key());
}
Object value = config.get(condition.getOption());
Evaluator evaluator = REGISTRY.get(operator);
return evaluator.evaluate(value, condition, config);
}
@SuppressWarnings({"rawtypes"})
private static Map<ConditionOperator, Evaluator> createRegistry() {
Map<ConditionOperator, Evaluator> m = new EnumMap<>(ConditionOperator.class);
// Equality
m.put(ConditionOperator.EQUAL, (v, c, cfg) -> Objects.equals(c.getExpectValue(), v));
m.put(ConditionOperator.NOT_EQUAL, (v, c, cfg) -> !Objects.equals(c.getExpectValue(), v));
// Numeric (null value -> false, preserving or() short-circuit)
m.put(View on GitHub (pinned to cf67b549a7)
Solutions
- Inspect the wrapped cause to identify which directory failed and why (NotFound, PermissionDenied, timeout).
- Ensure the SeaTunnel worker's credentials have read+execute (list) permission on every directory under the root, not just the root itself.
- Freeze concurrent modifications (deletes/renames) of the source tree while the job lists files, or point the scan at a stable snapshot path.
- Retry the job if the cause is transient (S3 throttling/network); consider fewer, larger directories to reduce listing pressure.
Example fix
// before hdfs dfs -chmod 700 /data/source/private_dir // worker can't list it // after hdfs dfs -chmod 755 /data/source/private_dir # or grant the job user read+execute
Defensive patterns
Strategy: retry
Validate before calling
java
// Pre-walk the tree and verify list permission on every directory
Files.walkFileTree(localRoot, new SimpleFileVisitor<>() {
@Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) {
if (!dir.toFile().canRead()) {
throw new IllegalStateException("No list permission on directory: " + dir);
}
return FileVisitResult.CONTINUE;
}
}); Try / catch
java
try {
scanner.scan(session, root, filter, consumer);
} catch (IOException e) {
if (e.getMessage().startsWith("Failed during source_listing for protocol=")) {
if (isTransient(e.getCause())) { /* S3 throttling, timeouts */ retryScan(); }
else LOG.error("Directory listing failed (check per-directory permissions, concurrent deletes): "
+ e.getMessage(), e.getCause());
}
} Prevention
- Grant the job user list permission on every subdirectory under the source root
- Avoid deleting/moving source directories while a job is listing files
- Enable storage client retries (S3 SDK, HDFS client) for transient throttling
- Keep source trees shallow; inspect e.getCause() for the failing directory
When it happens
Trigger: Calling scan where listing a traversed directory throws IOException — the directory was deleted mid-traversal, permission denied on a subdirectory, transient storage timeouts (S3 throttling, HDFS NameNode retries exhausted), or a listStatus failure on a specific child directory.
Common situations: Concurrent jobs/users deleting or moving directories during a scan; per-subdirectory permissions differing from the root; S3 rate limiting under large directory trees; flaky network to the storage backend.
Understand the failure class
Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.
Related errors
- Circular condition chain detected: '%s' already exists in th
- Failed during source_listing setup/scan for protocol=%s, pat
- SeaTunnelAPIErrorCode.CONFIG_VALIDATION_FAILED
- Listing table in database %s exception.
- Error while checking whether table exists under path:${baseP
AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10).
Data as JSON: /api/errors/0e5a3ac344797e35.
Report an issue: GitHub.