{"record":{"id":"fc6dc68fd6c63fc9","repo":"apache/hadoop","slug":"file-check-failed","errorCode":null,"errorMessage":"File check failed","messagePattern":"File check failed","errorType":"exception","errorClass":"FTPException","httpStatus":null,"severity":"error","filePath":"hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/ftp/FTPFileSystem.java","lineNumber":623,"sourceCode":"    } else if (isFile(client, absolute)) {\n      throw new ParentNotDirectoryException(String.format(\n          \"Can't make directory for path %s since it is a file.\", absolute));\n    }\n    return created;\n  }\n\n  /**\n   * Convenience method, so that we don't open a new connection when using this\n   * method from within another method. Otherwise every API invocation incurs\n   * the overhead of opening/closing a TCP connection.\n   */\n  private boolean isFile(FTPClient client, Path file) {\n    try {\n      return getFileStatus(client, file).isFile();\n    } catch (FileNotFoundException e) {\n      return false; // file does not exist\n    } catch (IOException ioe) {\n      throw new FTPException(\"File check failed\", ioe);\n    }\n  }\n\n  /*\n   * Assuming that parent of both source and destination is the same. Is the\n   * assumption correct or it is suppose to work like 'move' ?\n   */\n  @Override\n  public boolean rename(Path src, Path dst) throws IOException {\n    FTPClient client = connect();\n    try {\n      boolean success = rename(client, src, dst);\n      return success;\n    } finally {\n      disconnect(client);\n    }\n  }\n","sourceCodeStart":605,"sourceCodeEnd":641,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/ftp/FTPFileSystem.java#L605-L641","documentation":"Thrown by the private helper FTPFileSystem.isFile(FTPClient, Path), which shares one FTP connection across API calls to avoid reconnect overhead. It calls getFileStatus and treats FileNotFoundException as \"not a file\"; every other IOException (dropped control/data connection, 5xx reply, permission failure during LIST) is rethrown as FTPException(\"File check failed\") with the original cause attached.","triggerScenarios":"Invoking FTPFileSystem operations that internally probe isFile()/exists() on the shared client — e.g. rename(Path, Path) or getFileStatus — while the FTP session is broken: server killed the idle control connection, the passive data connection is blocked/refused, or the server returns an error reply while listing the path.","commonSituations":"vsftpd/proftpd idle_session_timeout killing the control channel between calls; firewalls/NAT dropping passive-mode data connections; wrong or expired credentials configured via fs.ftp.user.<host>/fs.ftp.password.<host>; probing paths inside directories the FTP user cannot list.","solutions":["Inspect the nested cause with exception.getCause() — the Commons Net reply string shows whether it is connectivity, auth, or permission","Verify reachability and credentials from the same machine with an external client (curl -u user ftp://host/) using the identical fs.ftp.* settings","Keep the control connection alive between operations (shorter idle gaps, keepalive settings) so the server does not drop the session mid-conversation","Confirm the directory holding the path is listable by the FTP user; grant list permission if missing","Retry the operation once after reconnecting — transient network blips surface here as a wrapped error"],"exampleFix":"// before\nif (fs.isFile(path)) { /* ... */ }  // FTPException(\"File check failed\") surfaces here\n\n// after\ntry {\n  if (fs.isFile(path)) { /* ... */ }\n} catch (FTPException e) {\n  Throwable cause = e.getCause();  // original IOException from getFileStatus\n  LOG.warn(\"FTP file check failed, cause: {}\", cause, e);\n  throw e;\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"catch org.apache.hadoop.fs.ftp.FTPException around the filesystem call, then branch on getCause(): FileNotFoundException means the path is gone (handle as absent); any other IOException means the FTP session itself failed — close and re-obtain the FileSystem before retrying.","preventionTips":["Reuse one FTPFileSystem instance per owner instead of reconnecting per operation","Keep the control connection active between calls or reconnect deliberately rather than letting it half-die","Always log the full cause chain, not just the wrapper message","Monitor FTP server session limits when many clients share one account"],"tags":["ftp","hadoop","filesystem","io","wrapped-exception"],"backgroundTag":"ftp-connection-failure","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-22T20:17:22.307Z"}