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

  1. Trace the Predicate only once; reuse the MDCPredicate directly
  2. Guard with `if (p instanceof MDCPredicate) use it else tracing(...)`
  3. 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

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


AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10). Data as JSON: /api/errors/18b11da6fc3b96c1. Report an issue: GitHub.