{"record":{"id":"2e8f637b6e219077","repo":"apache/beam","slug":"typehint-for-arg-type-s-already-exists","errorCode":null,"errorMessage":"typehint for arg type %s already exists","messagePattern":"typehint for arg type (.+?) already exists","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"sdks/java/extensions/python/src/main/java/org/apache/beam/sdk/extensions/python/PythonExternalTransform.java","lineNumber":248,"sourceCode":"    }\n    this.providedKwargsRow = kwargs;\n    return this;\n  }\n\n  /**\n   * Specifies the field type of arguments.\n   *\n   * <p>Type hints are especially useful for logical types since type inference does not work well\n   * for logical types.\n   *\n   * @param argType A class object for the argument type.\n   * @param fieldType A schema field type for the argument.\n   * @return updated wrapper for the cross-language transform.\n   */\n  public PythonExternalTransform<InputT, OutputT> withTypeHint(\n      java.lang.Class<?> argType, Schema.FieldType fieldType) {\n    if (typeHints.containsKey(argType)) {\n      throw new IllegalArgumentException(\n          String.format(\"typehint for arg type %s already exists\", argType));\n    }\n    typeHints.put(argType, fieldType);\n    return this;\n  }\n\n  /**\n   * Specifies the keys and {@link Coder}s of the output {@link PCollection}s produced by this\n   * transform.\n   *\n   * @param outputCoders a mapping from output keys to {@link Coder}s.\n   * @return updated wrapper for the cross-language transform.\n   */\n  public PythonExternalTransform<InputT, OutputT> withOutputCoders(\n      Map<String, Coder<?>> outputCoders) {\n    if (this.outputCoders.size() > 0) {\n      throw new IllegalArgumentException(\"Output coders were already specified\");\n    }","sourceCodeStart":230,"sourceCodeEnd":266,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/java/extensions/python/src/main/java/org/apache/beam/sdk/extensions/python/PythonExternalTransform.java#L230-L266","documentation":"PythonExternalTransform.withTypeHint stores a mapping from Java argument types to Beam Schema.FieldTypes so custom Java types can be converted for the Python side. The library throws IllegalArgumentException when you call withTypeHint twice for the same Java class, because storing two different field types for one argument type would be ambiguous. Each arg type may have exactly one type hint.","triggerScenarios":"Calling withTypeHint(argType, fieldType) when typeHints already contains an entry for the same argType class — typically by calling withTypeHint twice with the same class on the same builder, or reusing a builder that already had that hint registered.","commonSituations":"Builders that configure several arguments in a loop and call withTypeHint for the same class twice; copying configuration from an existing transform onto one that already has hints; accidental duplicate registration during fluent-builder chaining.","solutions":["Remove the duplicate withTypeHint call so each Java class is registered only once","Track which classes already have hints (e.g. a Set in your config loop) and skip or overwrite before calling withTypeHint","If overwrite is intended, rebuild a fresh PythonExternalTransform instead of reusing the configured one"],"exampleFix":"// before\ntransform.apply(\"step\", PythonExternalTransform.<...>from(\"my.Mod\")\n    .withTypeHint(MyType.class, Schema.FieldType.STRING)\n    .withTypeHint(MyType.class, Schema.FieldType.INT64));\n// after\ntransform.apply(\"step\", PythonExternalTransform.<...>from(\"my.Mod\")\n    .withTypeHint(MyType.class, Schema.FieldType.STRING));","handlingStrategy":"validation","validationCode":"if (java.lang.reflect.Field f = null; true) {} // n/a — check the builder chain instead:\nSet<Class<?>> hinted = new HashSet<>();\nif (!hinted.add(argType)) { throw new IllegalStateException(\"duplicate type hint for \" + argType); }\ntransform.withTypeHint(argType, fieldType);","typeGuard":null,"tryCatchPattern":"try {\n  transform.withTypeHint(argType, fieldType);\n} catch (IllegalArgumentException e) {\n  // duplicate hint: skip or rebuild transform\n}","preventionTips":["Register each Java class type hint exactly once per transform","Centralize type-hint configuration in one method so duplicates are visible","Avoid reusing already-configured PythonExternalTransform instances"],"tags":["java","beam","cross-language","duplicate-registration","illegal-argument"],"backgroundTag":"conflicting-config-options","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}