apache/hadoop · error · IllegalArgumentException

Proxy error: %s or %s set without the other.

Error message

Proxy error: %s or %s set without the other.

What it means

DefaultOBSClientFactory reads fs.obs.proxy.username (getTrimmed) and fs.obs.proxy.password (getPassword) when setting up the HTTP proxy for the OBS client. If exactly one of the two is configured (XOR check), initialization aborts with IllegalArgumentException 'Proxy error: fs.obs.proxy.username or fs.obs.proxy.password set without the other.' The OBS SDK requires both credentials together, so a half-configured proxy is rejected before any connection is attempted.

Source

Thrown at hadoop-cloud-storage-project/hadoop-huaweicloud/src/main/java/org/apache/hadoop/fs/obs/DefaultOBSClientFactory.java:197

        LOG.warn("Proxy host set without port. Using HTTP default "
            + OBSConstants.DEFAULT_HTTP_PORT);
        obsConf.getHttpProxy()
            .setProxyPort(OBSConstants.DEFAULT_HTTP_PORT);
      }
    }
    String proxyUsername = conf.getTrimmed(OBSConstants.PROXY_USERNAME);
    String proxyPassword = null;
    char[] proxyPass = conf.getPassword(OBSConstants.PROXY_PASSWORD);
    if (proxyPass != null) {
      proxyPassword = new String(proxyPass).trim();
    }
    if ((proxyUsername == null) != (proxyPassword == null)) {
      String msg =
          "Proxy error: " + OBSConstants.PROXY_USERNAME + " or "
              + OBSConstants.PROXY_PASSWORD
              + " set without the other.";
      LOG.error(msg);
      throw new IllegalArgumentException(msg);
    }
    obsConf.setHttpProxy(proxyHost, proxyPort, proxyUsername,
        proxyPassword);
    if (LOG.isDebugEnabled()) {
      LOG.debug(
          "Using proxy server {}:{} as user {} on "
              + "domain {} as workstation {}",
          obsConf.getHttpProxy().getProxyAddr(),
          obsConf.getHttpProxy().getProxyPort(),
          obsConf.getHttpProxy().getProxyUName(),
          obsConf.getHttpProxy().getDomain(),
          obsConf.getHttpProxy().getWorkstation());
    }
  }

  /**
   * Creates an {@link ObsClient} from the established configuration.
   *

View on GitHub (pinned to 2add963021)

Solutions

  1. Set BOTH fs.obs.proxy.username and fs.obs.proxy.password (or remove both to disable authenticated proxy).
  2. If the password comes from a credential provider, verify the entry exists: hadoop credential list -provider jceks://... and confirm the provider path config resolves in the same context (same user/classpath).
  3. Check for typos: keys are exactly fs.obs.proxy.username / fs.obs.proxy.password; per-bucket variants must mirror each other.
  4. If the proxy truly needs no auth, clear both keys and rely on fs.obs.proxy.host + fs.obs.proxy.port only.

Example fix

# before (core-site.xml)
<property><name>fs.obs.proxy.host</name><value>proxy.corp</value></property>
<property><name>fs.obs.proxy.port</name><value>8080</value></property>
<property><name>fs.obs.proxy.username</name><value>obsuser</value></property>
<!-- password missing -->

# after
<property><name>fs.obs.proxy.username</name><value>obsuser</value></property>
<property><name>fs.obs.proxy.password</name><value>obs-pass</value></property>
<!-- or store via: hadoop credential create fs.obs.proxy.password -value xxx -provider localjceks://...</property -->
Defensive patterns

Strategy: validation

Validate before calling

static boolean proxyConfigConsistent(Configuration conf) {
  String u = conf.getTrimmed("fs.obs.proxy.username");
  char[] p = conf.getPassword("fs.obs.proxy.password");
  return (u == null) == (p == null); // both set or both unset
}
if (!proxyConfigConsistent(conf)) throw new ConfigException("set both fs.obs.proxy.username and fs.obs.proxy.password");

Try / catch

try {
  obsFs.initialize(uri, conf);
} catch (IllegalArgumentException e) {
  if (String.valueOf(e.getMessage()).contains("fs.obs.proxy.username")) {
  	if (String.valueOf(e.getMessage()).contains("Proxy error")) {
      throw new ConfigException("Proxy credentials half-configured", e);
    }
  }
  throw e;
}

Prevention

When it happens

Trigger: Setting fs.obs.proxy.username in core-site.xml (or a job config) without fs.obs.proxy.password; providing the password only via a credential provider that fails to resolve (getPassword returns null → password side missing); trailing-whitespace/empty username trimmed to null; per-bucket config override (fs.obs.bucket.X.proxy.username) that forgets the matching password key.

Common situations: Adding proxy settings incrementally during corporate-network onboarding; copy-pasting an example config that only shows the username line; password moved to a JCEKS credential provider that is not on hadoop.security.credential.provider.path, so getPassword() yields null; typos in one of the two key names.

Related errors


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