{"record":{"id":"34468b7752b64c82","repo":"apache/beam","slug":"found-multiple-schematransformprovider-implementations-with-34468b","errorCode":null,"errorMessage":"Found multiple SchemaTransformProvider implementations with the same identifier {schemaTransformProvider.identifier()}","messagePattern":"Found multiple SchemaTransformProvider implementations with the same identifier (.+?)","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"sdks/java/managed/src/main/java/org/apache/beam/sdk/managed/ManagedSchemaTransformProvider.java","lineNumber":255,"sourceCode":"    Map<String, Map<String, String>> aliases = new HashMap<>();\n    for (Map.Entry<String, Object> entry : YamlUtils.loadFromStream(inputStream).entrySet()) {\n      aliases.put(entry.getKey(), (Map<String, String>) entry.getValue());\n    }\n    return aliases;\n  }\n\n  // We load providers separately, after construction, to prevent the\n  // 'ManagedSchemaTransformProvider' from being initialized in a recursive loop\n  // when being loaded using 'AutoValue'.\n  synchronized Map<String, SchemaTransformProvider> getAllProviders() {\n    if (this.providersCached) {\n      return schemaTransformProvidersCache;\n    }\n    try {\n      for (SchemaTransformProvider schemaTransformProvider :\n          ServiceLoader.load(SchemaTransformProvider.class)) {\n        if (schemaTransformProvidersCache.containsKey(schemaTransformProvider.identifier())) {\n          throw new IllegalArgumentException(\n              \"Found multiple SchemaTransformProvider implementations with the same identifier \"\n                  + schemaTransformProvider.identifier());\n        }\n        if (supportedIdentifiers == null\n            || supportedIdentifiers.contains(schemaTransformProvider.identifier())) {\n          if (schemaTransformProvider.identifier().equals(\"beam:transform:managed:v1\")) {\n            // Prevent recursively adding the 'ManagedSchemaTransformProvider'.\n            continue;\n          }\n          schemaTransformProvidersCache.put(\n              schemaTransformProvider.identifier(), schemaTransformProvider);\n        }\n      }\n      this.providersCached = true;\n      return schemaTransformProvidersCache;\n    } catch (Exception e) {\n      throw new RuntimeException(e.getMessage());\n    }","sourceCodeStart":237,"sourceCodeEnd":273,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/java/managed/src/main/java/org/apache/beam/sdk/managed/ManagedSchemaTransformProvider.java#L237-L273","documentation":"ManagedSchemaTransformProvider.getAllProviders discovers SchemaTransformProvider implementations via ServiceLoader and caches them by identifier(). If two providers on the classpath declare the same identifier, discovery cannot disambiguate and this IllegalArgumentException is thrown. It protects against silently picking the wrong implementation.","triggerScenarios":"Building/running a pipeline where the classpath (fat jar, shaded uber-jar, or project dependencies) contains two jars registering SchemaTransformProvider services with the same identifier, triggering provider discovery.","commonSituations":"Shading Beam IO modules into an uber-jar that duplicates service files, depending on two Beam versions transitively, or adding a custom provider that reuses an existing identifier like 'beam:schematransform:...'.","solutions":["Run `mvn dependency:tree` / gradle dependencies to find duplicate Beam IO or provider jars and exclude one.","If shading, merge/relocate service files so only one provider per identifier is registered.","Rename your custom provider's identifier() so it is unique.","Restrict the supportedIdentifiers passed to Managed so the conflicting provider is not required, after removing the duplicate."],"exampleFix":"// before: custom provider reuses existing id\npublic String identifier() { return \"beam:schematransform:sql_server:v1\"; }\n// after\npublic String identifier() { return \"myorg:schematransform:custom_sql_server:v1\"; }","handlingStrategy":"validation","validationCode":"Set<String> seen = new HashSet<>();\nfor (SchemaTransformProvider p : ServiceLoader.load(SchemaTransformProvider.class)) {\n  if (!seen.add(p.identifier())) throw new IllegalStateException(\"Duplicate provider id: \" + p.identifier());\n}","typeGuard":null,"tryCatchPattern":"try { pipeline.apply(Managed.read(Managed.BIGQUERY, config)); } catch (IllegalArgumentException e) { if (e.getMessage().contains(\"same identifier\")) { /* fix classpath duplicates */ } throw e; }","preventionTips":["Audit fat jars for duplicated META-INF/services entries.","Never reuse built-in beam: identifiers in custom providers.","Run discovery (Managed.read on a dummy id) in CI to catch classpath issues early."],"tags":["java","apache-beam","serviceloader","classpath"],"backgroundTag":"duplicate-service-registration","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-20T03:17:13.778Z"}