{"record":{"id":"147d0418ea478d8e","repo":"apache/seatunnel","slug":"already-an-mdccomparator","errorCode":null,"errorMessage":"Already an MDCComparator","messagePattern":"Already an MDCComparator","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"seatunnel-api/src/main/java/org/apache/seatunnel/api/tracing/MDCTracer.java","lineNumber":188,"sourceCode":"\n    public static <T> MDCPredicate<T> tracing(MDCContext context, Predicate<T> delegate) {\n        if (delegate instanceof MDCPredicate) {\n            throw new IllegalArgumentException(\"Already an MDCPredicate\");\n        }\n        return new MDCPredicate<>(context, delegate);\n    }\n\n    public static <T> MDCComparator<T> tracing(Comparator<T> delegate) {\n        return tracing(MDCContext.current(), delegate);\n    }\n\n    public static <T> MDCComparator<T> tracing(Long jobId, Comparator<T> delegate) {\n        return tracing(MDCContext.of(jobId), delegate);\n    }\n\n    public static <T> MDCComparator<T> tracing(MDCContext context, Comparator<T> delegate) {\n        if (delegate instanceof MDCComparator) {\n            throw new IllegalArgumentException(\"Already an MDCComparator\");\n        }\n        return new MDCComparator<>(context, delegate);\n    }\n\n    public static <T> MDCSupplier<T> tracing(Supplier<T> delegate) {\n        return tracing(MDCContext.current(), delegate);\n    }\n\n    public static <T> MDCSupplier<T> tracing(Long jobId, Supplier<T> delegate) {\n        return tracing(MDCContext.of(jobId), delegate);\n    }\n\n    public static <T> MDCSupplier<T> tracing(MDCContext context, Supplier<T> delegate) {\n        if (delegate instanceof MDCSupplier) {\n            throw new IllegalArgumentException(\"Already an MDCSupplier\");\n        }\n        return new MDCSupplier<>(context, delegate);\n    }","sourceCodeStart":170,"sourceCodeEnd":206,"githubUrl":"https://github.com/apache/seatunnel/blob/cf67b549a7a6c35fa0beb12d83c62892427ea919/seatunnel-api/src/main/java/org/apache/seatunnel/api/tracing/MDCTracer.java#L170-L206","documentation":"MDCTracer.tracing(context, Comparator) rejects a delegate already wrapped as MDCComparator with IllegalArgumentException. Double wrapping would snapshot/restore MDC state twice around a single comparison, corrupting restoration order.","triggerScenarios":"Calling tracing(jobId, comparator) or tracing(context, comparator) where comparator is already an MDCComparator from a previous tracing() call, e.g. sort comparators wrapped by both a sort utility and the caller.","commonSituations":"Sorting/merging code where a shared comparator factory already applies tracing and the call site wraps again.","solutions":["Trace the Comparator once, at the point where it is created","Pass through already-wrapped comparators: `if (c instanceof MDCComparator) return c;`","Deduplicate tracing across the utility and call-site layers"],"exampleFix":"// before\nMDCComparator<T> c = MDCTracer.tracing(jobId, MDCTracer.tracing(jobId, cmp));\n// after\nMDCComparator<T> c = MDCTracer.tracing(jobId, cmp);","handlingStrategy":"type-guard","validationCode":"MDCComparator<T> safeWrap(Long jobId, Comparator<T> c) {\n    return c instanceof MDCComparator ? (MDCComparator<T>) c : MDCTracer.tracing(jobId, c);\n}","typeGuard":"boolean isWrapped(Comparator<?> c) {\n    return c instanceof MDCComparator;\n}","tryCatchPattern":"try {\n    return MDCTracer.tracing(jobId, comparator);\n} catch (IllegalArgumentException e) {\n    return (MDCComparator<T>) comparator;\n}","preventionTips":["Trace comparators once at creation","Pass through already-wrapped comparators in sort/merge utilities","Keep tracing responsibility in a single factory per comparator type"],"tags":["java","mdc","tracing","double-wrap"],"backgroundTag":"invalid-argument-value","analyzedSha":"cf67b549a7a6c35fa0beb12d83c62892427ea919","analyzedAt":"2026-09-10T21:44:55.265Z","contentChangedAt":"2026-09-10T21:44:55.265Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}