pentaho/pentaho-kettle · error · FTPException

JobEntryFTP.SocksProxy.PortMissingException

Error message

JobEntryFTP.SocksProxy.PortMissingException

What it means

JobEntryFTP requires a SOCKS proxy port whenever a SOCKS proxy host is configured. If socksProxyHost is set but socksProxyPort is empty, the entry throws an FTPException with this localized message before attempting the FTP connection. FTPClient.initSOCKS needs both host and port to configure the JVM-wide SOCKS settings.

Solutions

  1. Set the SOCKS proxy port field in the FTP job entry dialog
  2. Verify the stored entry attributes include a non-empty socks proxy port
  3. Test the port with the actual proxy server (commonly 1080 for SOCKS)

Example fix

// before (dialog config)
SOCKS proxy host: proxy.example.com
SOCKS proxy port: (empty)
// after
SOCKS proxy host: proxy.example.com
SOCKS proxy port: 1080
Defensive patterns

Strategy: validation

Validate before calling

if (!Utils.isEmpty(socksProxyHost) && Utils.isEmpty(socksProxyPort)) { throw new IllegalArgumentException("SOCKS proxy port required when host is set"); }

Prevention

When it happens

Trigger: Running/executing the job entry with a SOCKS proxy host filled in the job entry dialog but the SOCKS proxy port field left blank.

Common situations: Copy-pasting proxy config with the port forgotten; assuming a default SOCKS port exists; configuration imported from XML/repertoire where the port attribute was empty or lost.

Understand the failure class

Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.

Related errors


AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13). Data as JSON: /api/errors/e38f5418bb583a92. Report an issue: GitHub.

Appendix: source

Thrown at plugins/get-file-with-ftp/impl/src/main/java/org/pentaho/di/job/entries/ftp/JobEntryFTP.java:977

      // Set the timeout
      int timeoutValue = Const.toInt( environmentSubstitute( timeout ), 10000 );
      ftpclient.setTimeout( timeoutValue );
      if ( isDetailed() ) {
        logDetailed( BaseMessages.getString( PKG, "JobEntryFTP.SetTimeout", String.valueOf( timeoutValue ) ) );
      }

      ftpclient.setControlEncoding( controlEncoding );
      if ( isDetailed() ) {
        logDetailed( BaseMessages.getString( PKG, "JobEntryFTP.SetEncoding", controlEncoding ) );
      }

      // If socks proxy server was provided
      if ( !Utils.isEmpty( socksProxyHost ) ) {
        if ( !Utils.isEmpty( socksProxyPort ) ) {
          FTPClient.initSOCKS( environmentSubstitute( socksProxyPort ), environmentSubstitute( socksProxyHost ) );
        } else {
          throw new FTPException( BaseMessages.getString(
            PKG, "JobEntryFTP.SocksProxy.PortMissingException", environmentSubstitute( socksProxyHost ),
            getName() ) );
        }
        // then if we have authentication information
        if ( !Utils.isEmpty( socksProxyUsername ) && !Utils.isEmpty( socksProxyPassword ) ) {
          FTPClient.initSOCKSAuthentication(
            environmentSubstitute( socksProxyUsername ), Utils.resolvePassword( this, socksProxyPassword ) );
        } else if ( !Utils.isEmpty( socksProxyUsername )
          && Utils.isEmpty( socksProxyPassword ) || Utils.isEmpty( socksProxyUsername )
          && !Utils.isEmpty( socksProxyPassword ) ) {
          // we have a username without a password or vica versa
          throw new FTPException( BaseMessages.getString(
            PKG, "JobEntryFTP.SocksProxy.IncompleteCredentials", environmentSubstitute( socksProxyHost ),
            getName() ) );
        }
      }

      // login to ftp host ...

View on GitHub (pinned to f3058517a1)