apache/seatunnel · error · IOException
Invalid user/password specified
Error message
Invalid user/password specified
What it means
SeaTunnelFTPFileSystem.initialize() derives credentials from the URI userinfo; when absent it reads fs.ftp.user.<host> and fs.ftp.password.<host> from the Hadoop configuration. If no URI userinfo exists and either the user or password config is null, it throws IOException('Invalid user/password specified').
Source
Thrown at seatunnel-connectors-v2/connector-file/connector-file-ftp/src/main/java/org/apache/seatunnel/connectors/seatunnel/file/ftp/system/SeaTunnelFTPFileSystem.java:116
String host = uri.getHost();
host = (host == null) ? conf.get(FS_FTP_HOST, null) : host;
if (host == null) {
throw new IOException("Invalid host specified");
}
conf.set(FS_FTP_HOST, host);
// get port information from uri, (overrides info in conf)
int port = uri.getPort();
port = (port == -1) ? FTP.DEFAULT_PORT : port;
conf.setInt("fs.ftp.host.port", port);
// get user/password information from URI (overrides info in conf)
String userAndPassword = uri.getUserInfo();
if (userAndPassword == null) {
String user = conf.get("fs.ftp.user." + host, null);
String password = conf.get("fs.ftp.password." + host, null);
if (user == null || password == null) {
throw new IOException("Invalid user/password specified");
}
userAndPassword = user + ":" + password;
}
String[] userPasswdInfo = userAndPassword.split(":");
conf.set(FS_FTP_USER_PREFIX + host, userPasswdInfo[0]);
if (userPasswdInfo.length > 1) {
conf.set(FS_FTP_PASSWORD_PREFIX + host, userPasswdInfo[1]);
} else {
conf.set(FS_FTP_PASSWORD_PREFIX + host, null);
}
setConf(conf);
this.uri = uri;
}
/**
* Connect to the FTP server using configuration parameters *
*
* @return An FTPClient instanceView on GitHub (pinned to cf67b549a7)
Solutions
- Embed credentials in the URI: ftp://user:password@ftp.example.com/path
- Or set both conf keys fs.ftp.user.<host> and fs.ftp.password.<host> with <host> exactly matching the URI host
- Ensure the password does not break the user:password split (avoid ':' or URI-encode it)
Example fix
// before
path = "ftp://ftp.example.com/data" // no credentials anywhere
// after
path = "ftp://user:password@ftp.example.com/data"
// or: conf.set("fs.ftp.user.ftp.example.com", "user"); conf.set("fs.ftp.password.ftp.example.com", "password"); Defensive patterns
Strategy: validation
Validate before calling
// Java
URI uri = URI.create(path);
boolean hasUserInfo = uri.getUserInfo() != null;
String host = uri.getHost() != null ? uri.getHost() : conf.get("fs.ftp.host");
boolean hasConfCreds = conf.get("fs.ftp.user." + host) != null
&& conf.get("fs.ftp.password." + host) != null;
if (!hasUserInfo && !hasConfCreds) {
throw new IllegalArgumentException("Provide ftp user:pass in URI or fs.ftp.user/password." + host);
} Try / catch
try {
fileSystem.initialize(uri, conf);
} catch (IOException e) {
if ("Invalid user/password specified".equals(e.getMessage())) {
throw new IllegalArgumentException("Missing FTP credentials for host " + host, e);
}
throw e;
} Prevention
- Prefer credentials embedded in the URI (ftp://user:pass@host)
- If using conf keys, the suffix must exactly equal the URI host
- Avoid ':' in passwords or URI-encode them to keep user:pass parsing intact
- Never commit credentials; inject them from a secret store
When it happens
Trigger: Calling initialize() with a URI without user info (no user:pass@host) while fs.ftp.user.<host> or fs.ftp.password.<host> is not set in the Configuration; host here is the URI host or the fs.ftp.host fallback.
Common situations: Credentials omitted from the SeaTunnel FTP source/sink config; config keys written with the wrong host suffix (must match exactly, e.g. fs.ftp.user.ftp.example.com); URI-encoded password containing ':' mis-split later; anonymous FTP attempted without explicit user/password entries.
Related errors
- Invalid host specified
- Option '${valuesAndOptions[index + 1]}' is not valid for the
- AzureCosmosDB requires key, primary_key, secondary_key, or a
- Unknown ftp connection mode: ${mode}
- Login failed on server - %s, port - %d as user '%s', reply c
AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10).
Data as JSON: /api/errors/2fa5c1cef3e88853.
Report an issue: GitHub.