apache/hadoop · error · IOException

Login failed on server - {host}, port - {port} as user '{use

Error message

Login failed on server - {host}, port - {port} as user '{user}'

What it means

The TCP connection and control-channel greeting succeeded (positive completion reply), but FTPClient.login(user, password) returned false — the server rejected the credentials. FTPFileSystem takes user/password from the URI userinfo or from the fs.ftp.user.<host> / fs.ftp.password.<host> keys (note the host suffix).

Source

Thrown at hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/ftp/FTPFileSystem.java:162

    String host = conf.get(FS_FTP_HOST);
    int port = conf.getInt(FS_FTP_HOST_PORT, FTP.DEFAULT_PORT);
    String user = conf.get(FS_FTP_USER_PREFIX + host);
    String password = conf.get(FS_FTP_PASSWORD_PREFIX + host);
    client = new FTPClient();
    client.connect(host, port);
    int reply = client.getReplyCode();
    if (!FTPReply.isPositiveCompletion(reply)) {
      throw NetUtils.wrapException(host, port,
                   NetUtils.UNKNOWN_HOST, 0,
                   new ConnectException("Server response " + reply));
    } else if (client.login(user, password)) {
      client.setFileTransferMode(getTransferMode(conf));
      client.setFileType(FTP.BINARY_FILE_TYPE);
      client.setBufferSize(DEFAULT_BUFFER_SIZE);
      setTimeout(client, conf);
      setDataConnectionMode(client, conf);
    } else {
      throw new IOException("Login failed on server - " + host + ", port - "
          + port + " as user '" + user + "'");
    }

    return client;
  }

  /**
   * Set the FTPClient's timeout based on configuration.
   * FS_FTP_TIMEOUT is set as timeout (defaults to DEFAULT_TIMEOUT).
   */
  @VisibleForTesting
  void setTimeout(FTPClient client, Configuration conf) {
    long timeout = conf.getLong(FS_FTP_TIMEOUT, DEFAULT_TIMEOUT);
    client.setControlKeepAliveTimeout(timeout);
  }

  /**
   * Set FTP's transfer mode based on configuration. Valid values are

View on GitHub (pinned to 2add963021)

Solutions

  1. Verify credentials outside Hadoop first: curl -u user:pass ftp://host/ or lftp ftp://user@host
  2. Set credentials explicitly with the correct host suffix: conf.set("fs.ftp.user." + host, user) and conf.set("fs.ftp.password." + host, password)
  3. Avoid embedding passwords with ':' or '@' in the URI userinfo; use the config keys instead
  4. Check whether the account is locked/expired or the server requires a specific auth mechanism

Example fix

// before
conf.set("fs.ftp.host", "ftp.example.com");
conf.set("fs.ftp.user.ftp.example.com", "alice");
conf.set("fs.ftp.password.example.com", "secret"); // wrong suffix -> login fails

// after
conf.set("fs.ftp.host", "ftp.example.com");
conf.set("fs.ftp.user.ftp.example.com", "alice");
conf.set("fs.ftp.password.ftp.example.com", "secret");
Defensive patterns

Strategy: try-catch

Validate before calling

// preflight credentials with a raw client before running the job
try (FTPClient probe = new FTPClient()) {
  probe.connect(host, port);
  if (!probe.login(user, password)) {
    throw new IllegalArgumentException("FTP credentials rejected for " + user);
  }
  probe.logout();
}

Try / catch

try {
  fs = path.getFileSystem(conf);
  fs.open(someFile);
} catch (IOException e) {
  if (e.getMessage() != null && e.getMessage().startsWith("Login failed")) {
    // fail fast with actionable message instead of retrying
    throw new IOException("FTP login rejected - check fs.ftp.user.<host>/fs.ftp.password.<host>", e);
  }
  throw e;
}

Prevention

When it happens

Trigger: Every filesystem operation calls connect(); wrong user or password, expired/locked account, or credentials read from the wrong config key (host suffix mismatch) all end here. Note initialize() requires both user and password non-null (it splits userinfo on ':' and requires two parts).

Common situations: Password rotated on the FTP server but not in job config; fs.ftp.user.<host> configured with a different host string than fs.ftp.host; passwords containing ':' or '@' breaking the URI userinfo split; server disallowing anonymous logins.

Related errors


AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22). Data as JSON: /api/errors/322fbe8dcc4893b3. Report an issue: GitHub.