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

  1. Check the URN spelling against the transforms published by the service and fix it in the pipeline construction code.
  2. Add the transform's provider to the service's allowlist / expansion service config file and restart the service.
  3. 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

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


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)