apache/beam · error · java.lang.IllegalArgumentException

Kwargs were specified both directly and as a Row object

Error message

Kwargs were specified both directly and as a Row object

What it means

PythonExternalTransform lets you supply Python keyword arguments either as individual withKwarg(name, value) calls (accumulated in kwargsMap) or as a single Beam Row via withKwargs(Row). Once a Row was provided, adding an individual kwarg would be ambiguous about ordering/precedence, so withKwarg throws IllegalArgumentException.

Solutions

  1. Pass all arguments through one mechanism: add the extra field to the Row before calling withKwargs.
  2. Use only withKwarg calls for every argument and drop the Row-based withKwargs call.
  3. Rebuild the transform: if you need both, convert the Row's fields into withKwarg calls instead (withKwargs(Row) must be the only source).

Example fix

// before
transform.withKwargs(row).withKwarg("extra", 1); // IllegalArgumentException
// after
Row newRow = Row.withSchema(row.getSchema()).addValues(row.getValues()).addValue(1).build();
transform.withKwargs(newRow);
Defensive patterns

Strategy: validation

Validate before calling

// Java: only allow withKwarg when no Row was provided
if (transformProvidedKwargsRow) {
  throw new IllegalStateException("Add the field to the Row instead of calling withKwarg");
}

Try / catch

try { return transform.withKwargs(row); } catch (IllegalArgumentException e) { if (e.getMessage().contains("both directly and as a Row")) { /* unify kwargs into a single representation */ } else throw e; }

Prevention

When it happens

Trigger: Calling .withKwargs(row) and then .withKwarg(name, value) on the same PythonExternalTransform builder.

Common situations: Adding one extra argument to an existing transform configuration that was already built from a Row; composing wrapper helpers where one path uses Row-based kwargs and another appends individual kwargs.

Related errors


AI-assisted analysis of apache/beam@12126d8942 (2026-09-13). Data as JSON: /api/errors/736baf93862295d7. Report an issue: GitHub.

Appendix: source

Thrown at sdks/java/extensions/python/src/main/java/org/apache/beam/sdk/extensions/python/PythonExternalTransform.java:200

  public PythonExternalTransform<InputT, OutputT> withArgs(@NonNull Object... args) {
    @Nullable Object @NonNull [] result =
        Arrays.copyOf(this.argsArray, this.argsArray.length + args.length);
    System.arraycopy(args, 0, result, this.argsArray.length, args.length);
    this.argsArray = result;
    return this;
  }

  /**
   * Specifies a single keyword argument for the Python cross-language transform. This may be
   * invoked multiple times to add more than one keyword argument.
   *
   * @param name argument name.
   * @param value argument value
   * @return updated wrapper for the cross-language transform.
   */
  public PythonExternalTransform<InputT, OutputT> withKwarg(String name, Object value) {
    if (providedKwargsRow != null) {
      throw new IllegalArgumentException("Kwargs were specified both directly and as a Row object");
    }
    kwargsMap.put(name, value);
    return this;
  }

  /**
   * Specifies keyword arguments for the Python cross-language transform. If invoked more than once,
   * new keyword arguments map will be added to the previously prided keyword arguments.
   *
   * @return updated wrapper for the cross-language transform.
   */
  public PythonExternalTransform<InputT, OutputT> withKwargs(Map<String, Object> kwargs) {
    if (providedKwargsRow != null) {
      throw new IllegalArgumentException("Kwargs were specified both directly and as a Row object");
    }
    kwargsMap.putAll(kwargs);
    return this;
  }

View on GitHub (pinned to 12126d8942)