Copilot commented on code in PR #11823:
URL: https://github.com/apache/seatunnel/pull/11823#discussion_r3811674103


##########
seatunnel-connectors-v2/connector-file/connector-file-base/src/main/java/org/apache/seatunnel/connectors/seatunnel/file/hadoop/HadoopFileSystemProxy.java:
##########
@@ -469,6 +469,69 @@ private void initializeWithKerberosLogin() throws 
IOException, InterruptedExcept
         log.info("Create FileSystem success with Kerberos: {}.", 
hadoopConf.getKerberosPrincipal());
     }
 
+    /**
+     * Creates the Hadoop {@link FileSystem} for the given configuration, 
rewriting a classpath
+     * mismatch into a diagnosable failure.
+     *
+     * <p>{@code FileSystem.get()} constructs a {@code DFSClient}, which 
reaches into Hadoop
+     * internals (e.g. {@code FsTracer}) whose method signatures have changed 
across Hadoop
+     * releases. If the Hadoop client jars actually resolved at runtime (this 
dependency is {@code
+     * provided}, so it comes from the deployment environment, not this 
project's shaded jar) don't
+     * match what SeaTunnel was built against, that surfaces as a raw {@link 
LinkageError} deep in
+     * Hadoop's own code with no indication of the real cause.
+     *
+     * <p>Nothing about that failure is specific to one authentication mode, 
so all three {@code
+     * FileSystem.get()} call sites in this class -- the plain path, the 
Kerberos path and the
+     * remote-user path -- are routed through here.
+     *
+     * @param configuration Hadoop configuration to build the filesystem from
+     * @return the filesystem for {@code configuration}
+     * @throws IOException if the filesystem cannot be created, including the 
diagnostic rewrite of
+     *     a Hadoop client version mismatch
+     */
+    private static FileSystem getFileSystemWithDiagnostics(Configuration 
configuration)
+            throws IOException {
+        return wrapClasspathMismatch(() -> FileSystem.get(configuration));
+    }
+
+    @FunctionalInterface
+    interface FileSystemSupplier {
+        FileSystem get() throws IOException;
+    }
+
+    /**
+     * Invokes {@code supplier} and rewrites a {@link LinkageError} raised 
while loading or linking
+     * Hadoop classes into an {@link IOException} that names the likely Hadoop 
client version
+     * mismatch, keeping the original error as the cause.
+     *
+     * <p>Only {@code LinkageError} is caught -- {@code NoSuchMethodError}, 
{@code
+     * NoClassDefFoundError}, {@code NoSuchFieldError} and {@code 
IncompatibleClassChangeError} are
+     * all plausible symptoms of the same jar mismatch -- so unrelated errors 
such as {@code
+     * OutOfMemoryError} still propagate untouched, as does an {@link 
IOException} raised by the
+     * supplier itself.
+     *
+     * @param supplier filesystem acquisition to guard
+     * @return whatever {@code supplier} returns
+     * @throws IOException the supplier's own {@code IOException}, or a 
diagnostic one wrapping a
+     *     {@code LinkageError}
+     */
+    static FileSystem wrapClasspathMismatch(FileSystemSupplier supplier) 
throws IOException {
+        try {
+            return supplier.get();
+        } catch (LinkageError e) {
+            throw new IOException(
+                    "Failed to initialize Hadoop FileSystem, likely due to a 
Hadoop client "
+                            + "version mismatch between SeaTunnel and the 
Hadoop jars resolved "
+                            + "at runtime (the Hadoop dependency here is 
`provided`, so it comes "
+                            + "from your deployment environment, not a bundled 
version). This "
+                            + "connector is built and tested against Hadoop 
3.1.4 (see "
+                            + "seatunnel-hadoop3-3.1.4-uber in the reactor 
pom); check that the "
+                            + "Hadoop client jars on the classpath are 
compatible with that "
+                            + "version.",
+                    e);

Review Comment:
   The message hardcodes the target Hadoop version (`3.1.4`) and an internal 
artifact name; this will become stale the next time the connector’s Hadoop 
baseline changes. Consider centralizing the target Hadoop version into a single 
constant (or a build-time injected property) and referencing that constant here 
so updates don’t require hunting through strings.



##########
seatunnel-connectors-v2/connector-file/connector-file-base/src/main/java/org/apache/seatunnel/connectors/seatunnel/file/hadoop/HadoopFileSystemProxy.java:
##########
@@ -469,6 +469,69 @@ private void initializeWithKerberosLogin() throws 
IOException, InterruptedExcept
         log.info("Create FileSystem success with Kerberos: {}.", 
hadoopConf.getKerberosPrincipal());
     }
 
+    /**
+     * Creates the Hadoop {@link FileSystem} for the given configuration, 
rewriting a classpath
+     * mismatch into a diagnosable failure.
+     *
+     * <p>{@code FileSystem.get()} constructs a {@code DFSClient}, which 
reaches into Hadoop
+     * internals (e.g. {@code FsTracer}) whose method signatures have changed 
across Hadoop
+     * releases. If the Hadoop client jars actually resolved at runtime (this 
dependency is {@code
+     * provided}, so it comes from the deployment environment, not this 
project's shaded jar) don't
+     * match what SeaTunnel was built against, that surfaces as a raw {@link 
LinkageError} deep in
+     * Hadoop's own code with no indication of the real cause.
+     *
+     * <p>Nothing about that failure is specific to one authentication mode, 
so all three {@code
+     * FileSystem.get()} call sites in this class -- the plain path, the 
Kerberos path and the
+     * remote-user path -- are routed through here.
+     *
+     * @param configuration Hadoop configuration to build the filesystem from
+     * @return the filesystem for {@code configuration}
+     * @throws IOException if the filesystem cannot be created, including the 
diagnostic rewrite of
+     *     a Hadoop client version mismatch
+     */
+    private static FileSystem getFileSystemWithDiagnostics(Configuration 
configuration)
+            throws IOException {
+        return wrapClasspathMismatch(() -> FileSystem.get(configuration));
+    }
+
+    @FunctionalInterface
+    interface FileSystemSupplier {
+        FileSystem get() throws IOException;
+    }
+
+    /**
+     * Invokes {@code supplier} and rewrites a {@link LinkageError} raised 
while loading or linking
+     * Hadoop classes into an {@link IOException} that names the likely Hadoop 
client version
+     * mismatch, keeping the original error as the cause.
+     *
+     * <p>Only {@code LinkageError} is caught -- {@code NoSuchMethodError}, 
{@code
+     * NoClassDefFoundError}, {@code NoSuchFieldError} and {@code 
IncompatibleClassChangeError} are
+     * all plausible symptoms of the same jar mismatch -- so unrelated errors 
such as {@code
+     * OutOfMemoryError} still propagate untouched, as does an {@link 
IOException} raised by the
+     * supplier itself.
+     *
+     * @param supplier filesystem acquisition to guard
+     * @return whatever {@code supplier} returns
+     * @throws IOException the supplier's own {@code IOException}, or a 
diagnostic one wrapping a
+     *     {@code LinkageError}
+     */
+    static FileSystem wrapClasspathMismatch(FileSystemSupplier supplier) 
throws IOException {
+        try {
+            return supplier.get();
+        } catch (LinkageError e) {
+            throw new IOException(
+                    "Failed to initialize Hadoop FileSystem, likely due to a 
Hadoop client "
+                            + "version mismatch between SeaTunnel and the 
Hadoop jars resolved "
+                            + "at runtime (the Hadoop dependency here is 
`provided`, so it comes "
+                            + "from your deployment environment, not a bundled 
version). This "
+                            + "connector is built and tested against Hadoop 
3.1.4 (see "
+                            + "seatunnel-hadoop3-3.1.4-uber in the reactor 
pom); check that the "
+                            + "Hadoop client jars on the classpath are 
compatible with that "
+                            + "version.",

Review Comment:
   The rewritten `IOException` message doesn’t include the specific linkage 
failure (error class + original message). Including something like the 
`LinkageError`’s concrete type and message (while still keeping it as the 
cause) would make the diagnostic more actionable from logs where the cause 
stacktrace might be truncated.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to