apache/beam · error · IllegalArgumentException
Unexpected expansion service address. Expected to be in the
Error message
Unexpected expansion service address. Expected to be in the format "<host>:<port>"
What it means
When an expansion service address is given, PythonExternalTransform.expand parses it as "<host>:<port>" so it can wait for the service port before expansion. The library throws IllegalArgumentException if the address has no colon or the colon is the first character, meaning it cannot extract a valid host/port pair.
Source
Thrown at sdks/java/extensions/python/src/main/java/org/apache/beam/sdk/extensions/python/PythonExternalTransform.java:474
private boolean isDockerAvailable() {
String executable = "docker";
try {
new ProcessBuilder(executable, "--version").start().waitFor();
return true;
} catch (IOException | InterruptedException exn) {
// Ignore.
}
return false;
}
@Override
public OutputT expand(InputT input) {
try {
ExternalTransforms.ExternalConfigurationPayload payload = generatePayload();
if (!Strings.isNullOrEmpty(expansionService)) {
int portIndex = expansionService.lastIndexOf(':');
if (portIndex <= 0) {
throw new IllegalArgumentException(
"Unexpected expansion service address. Expected to be in the "
+ "format \"<host>:<port>\"");
}
PythonService.waitForPort(
expansionService.substring(0, portIndex),
Integer.parseInt(expansionService.substring(portIndex + 1, expansionService.length())),
15000);
return apply(input, expansionService, payload);
} else {
OutputT output = null;
int port = PythonService.findAvailablePort();
PipelineOptionsFactory.register(PythonExternalTransformOptions.class);
PythonExternalTransformOptions options =
input.getPipeline().getOptions().as(PythonExternalTransformOptions.class);
boolean useTransformService = options.getUseTransformService();
@Nullable String customBeamRequirement = options.getCustomBeamRequirement();
boolean pythonAvailable = isPythonAvailable();
boolean dockerAvailable = isDockerAvailable();View on GitHub (pinned to 12126d8942)
Solutions
- Pass the full address including port, e.g. "localhost:5000"
- If relying on the default expansion service, do not set expansionService at all (pass null/empty) so the address check is skipped
- Validate the address format with a regex before calling withExpansionService
Example fix
// before
transform.withExpansionService("localhost"); // throws
// after
transform.withExpansionService("localhost:5000"); Defensive patterns
Strategy: validation
Validate before calling
if (expansionService != null && !expansionService.isEmpty()) {
int i = expansionService.lastIndexOf(':');
if (i <= 0) throw new IllegalArgumentException("expansionService must be <host>:<port>");
Integer.parseInt(expansionService.substring(i + 1));
}
transform.withExpansionService(expansionService); Type guard
boolean isValidServiceAddr(String s) {
if (s == null || s.isEmpty()) return true; // default service
int i = s.lastIndexOf(':');
return i > 0 && i < s.length() - 1;
} Try / catch
try {
transform.withExpansionService(addr);
} catch (IllegalArgumentException e) {
// fall back to default expansion service or fix address
} Prevention
- Always pass host:port form, e.g. localhost:5000
- Leave expansionService unset to use the default service
- Validate with a regex like ^[^:]+:\\d+$ before configuring
When it happens
Trigger: Setting expansionService via withExpansionService or the constructor to a value like "localhost" (no port), ":5000" (empty host, portIndex == 0), or any string whose lastIndexOf(':') is <= 0.
Common situations: Copy-pasting a service URL without the port; using a URI like "sc://host" scheme syntax; forgetting the default port; typos in the address.
Understand the failure class
Background: "Invalid URL" errors: why new URL(), URI.parse, and reqwest::Url reject your string — missing scheme, whitespace, and bad path format — this error's family across 39 libraries.
Related errors
- Cannot merge schemas with different numbers of fields. schem
- Unsupported type of %s: %s
- expansion service error: %s
- Conflicting registrations for: %s
- A transform cannot be initiated using the provided config ro
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/46207e9617d943cb.
Report an issue: GitHub.