apache/seatunnel · error · IllegalArgumentException
Already an MDCPredicate
Error message
Already an MDCPredicate
What it means
MDCTracer.tracing(context, Predicate) rejects a delegate already wrapped as MDCPredicate with IllegalArgumentException, failing fast instead of stacking two MDC capture/restore layers around one predicate test.
Source
Thrown at seatunnel-api/src/main/java/org/apache/seatunnel/api/tracing/MDCTracer.java:173
public static <T, R> MDCFunction<T, R> tracing(MDCContext context, Function<T, R> delegate) {
if (delegate instanceof MDCFunction) {
throw new IllegalArgumentException("Already an MDCFunction");
}
return new MDCFunction<>(context, delegate);
}
public static <T> MDCPredicate<T> tracing(Predicate<T> delegate) {
return tracing(MDCContext.current(), delegate);
}
public static <T> MDCPredicate<T> tracing(Long jobId, Predicate<T> delegate) {
return tracing(MDCContext.of(jobId), delegate);
}
public static <T> MDCPredicate<T> tracing(MDCContext context, Predicate<T> delegate) {
if (delegate instanceof MDCPredicate) {
throw new IllegalArgumentException("Already an MDCPredicate");
}
return new MDCPredicate<>(context, delegate);
}
public static <T> MDCComparator<T> tracing(Comparator<T> delegate) {
return tracing(MDCContext.current(), delegate);
}
public static <T> MDCComparator<T> tracing(Long jobId, Comparator<T> delegate) {
return tracing(MDCContext.of(jobId), delegate);
}
public static <T> MDCComparator<T> tracing(MDCContext context, Comparator<T> delegate) {
if (delegate instanceof MDCComparator) {
throw new IllegalArgumentException("Already an MDCComparator");
}
return new MDCComparator<>(context, delegate);
}View on GitHub (pinned to cf67b549a7)
Solutions
- Trace the Predicate only once; reuse the MDCPredicate directly
- Guard with `if (p instanceof MDCPredicate) use it else tracing(...)`
- Remove tracing from the inner helper layer
Example fix
// before MDCPredicate<T> p = MDCTracer.tracing(jobId, MDCTracer.tracing(jobId, pred)); // after MDCPredicate<T> p = MDCTracer.tracing(jobId, pred);
Defensive patterns
Strategy: type-guard
Validate before calling
MDCPredicate<T> safeWrap(Long jobId, Predicate<T> p) {
return p instanceof MDCPredicate ? (MDCPredicate<T>) p : MDCTracer.tracing(jobId, p);
} Type guard
boolean isWrapped(Predicate<?> p) {
return p instanceof MDCPredicate;
} Try / catch
try {
return MDCTracer.tracing(jobId, predicate);
} catch (IllegalArgumentException e) {
return (MDCPredicate<T>) predicate;
} Prevention
- Wrap predicates once where they are defined
- Do not double-wrap predicates passed through DSL helpers
- Check instanceof MDCPredicate before applying tracing
When it happens
Trigger: Calling tracing(jobId, predicate) or tracing(context, predicate) where predicate is already an MDCPredicate from an earlier tracing() call, e.g. filter predicates wrapped twice in a pipeline.
Common situations: Filter chains where both a DSL helper and the submission code trace the same Predicate; reusing library-provided traced predicates and wrapping again.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Already an MDCRunnable
- Already an MDCCallable
- Already an MDCExecutor
- Already an MDCConsumer
- Already an MDCFunction
AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10).
Data as JSON: /api/errors/18b11da6fc3b96c1.
Report an issue: GitHub.