apache/beam · error · java.lang.UnsupportedOperationException
Unknown urn:
Error message
Unknown urn:
What it means
Thrown by ExpansionService.expand when the URN in the expansion request does not match any registered transform provider and is not a schema-transform URN either. The service first checks its configured allowlist/registered providers, then falls back to the generic schema-transform path; if both fail it reports the URN as unknown.
Solutions
- Check the URN spelling against the transforms published by the service and fix it in the pipeline construction code.
- Add the transform's provider to the service's allowlist / expansion service config file and restart the service.
- Ensure the jar containing the transform provider is on the expansion service classpath (e.g. via --expansionJar or the classpath flag).
Example fix
// before
pcollection.apply("Kafka Read", "kafka:read:v1", ...); // unknown urn
// after
pcollection.apply("Kafka Read", "beam:schematransform:org.apache.beam:kafka_read:v1", ...); Defensive patterns
Strategy: try-catch
Validate before calling
Set<String> known = expansionService.listKnownUrns(); // or inspect service logs/config
if (!known.contains(urn) && !urn.startsWith("beam:schematransform:")) {
throw new IllegalStateException("URN not served by this expansion service: " + urn);
} Try / catch
try {
service.expand(request);
} catch (UnsupportedOperationException e) {
if (e.getMessage().startsWith("Unknown urn:")) { /* add provider to allowlist / fix URN */ }
throw e;
} Prevention
- Copy URNs from the transform provider's documented URN string, never by hand.
- Keep transform jars on the expansion service classpath.
- Whitelist the transform family in the allowlist config so providers register.
When it happens
Trigger: Calling ExpansionService.expand with a request whose transform spec URN is misspelled, was never registered via the allowlist/config file, or refers to a transform not present on the service's classpath.
Common situations: Typo in the URN string; expansion service started without the jar containing the requested transform; transform exists but is excluded by the allowlist so the provider lookup returns null; client and service Beam versions disagree on URN naming (e.g. 'beam:schematransform:...' vs legacy names).
Understand the failure class
Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.
Related errors
- A transform cannot be initiated using the provided config…
- Conflicting registrations for
- Error decoding payload
- error in startAutomatedJavaExpansionService
- expansion service error
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/cbb1ab0edd6430c0.
Report an issue: GitHub.
Appendix: source
Thrown at sdks/java/expansion-service/src/main/java/org/apache/beam/sdk/expansion/service/ExpansionService.java:646
commandLineOptions.as(ExpansionServiceOptions.class).getJavaClassLookupAllowlist();
assert allowList != null;
transformProvider = new JavaClassLookupTransformProvider(allowList);
} else if (getUrn(SCHEMA_TRANSFORM).equals(urn)) {
try {
String underlyingIdentifier =
ExternalTransforms.SchemaTransformPayload.parseFrom(
request.getTransform().getSpec().getPayload())
.getIdentifier();
transformProvider = getRegisteredTransforms().get(underlyingIdentifier);
} catch (InvalidProtocolBufferException e) {
throw new RuntimeException(e);
}
transformProvider =
transformProvider != null
? transformProvider
: ExpansionServiceSchemaTransformProvider.of();
} else {
throw new UnsupportedOperationException("Unknown urn: " + urn);
}
}
// Use expansion config file provided in commandLineOptions if not available
// in the expansion request options.
String configFileFromPipelineOptions =
pipeline.getOptions().as(ExpansionServiceOptions.class).getExpansionServiceConfigFile();
String configFileFromCommandLineOptions =
commandLineOptions.as(ExpansionServiceOptions.class).getExpansionServiceConfigFile();
if (configFileFromPipelineOptions == null && configFileFromCommandLineOptions != null) {
pipeline
.getOptions()
.as(ExpansionServiceOptions.class)
.setExpansionServiceConfigFile(configFileFromCommandLineOptions);
}
List<String> classpathResources =View on GitHub (pinned to 12126d8942)