apache/beam · error · IllegalArgumentException

Empty argument value is only allowed for String, String Arra

Error message

Empty argument value is only allowed for String, String Array, Collections of Strings or any of these types in a parameterized ValueProvider, but received: %s

What it means

An empty string option value was given for a type that cannot accept emptiness. Beam only allows empty values for String, String arrays, Collections of Strings, or ValueProviders parameterized by these; anything else throws IllegalArgumentException naming the generic type.

Source

Thrown at sdks/java/core/src/main/java/org/apache/beam/sdk/options/PipelineOptionsFactory.java:2053

    JavaType unwrappedType =
        type.equals(ValueProvider.class) ? genericType.containedType(0) : genericType;

    Class<?> containedType = unwrappedType.getRawClass();
    if (unwrappedType.getRawClass().isArray()) {
      containedType = unwrappedType.getRawClass().getComponentType();
    } else if (Collection.class.isAssignableFrom(unwrappedType.getRawClass())) {
      JavaType innerType = unwrappedType.containedType(0);
      // Note that raw types are allowed, hence the null check.
      containedType = innerType == null ? String.class : innerType.getRawClass();
    }
    if (!containedType.equals(String.class)) {
      String msg =
          String.format(
              "Empty argument value is only allowed for String, String Array, Collections of"
                  + " Strings or any of these types in a parameterized ValueProvider, but"
                  + " received: %s",
              genericTypeName);
      throw new IllegalArgumentException(msg);
    }
  }

  /** Hold all data which can change after a classloader change. */
  static final class Cache {
    private final Map<String, Class<? extends PipelineRunner<?>>> supportedPipelineRunners;

    /** The set of options that have been registered and visible to the user. */
    private final Set<Class<? extends PipelineOptions>> registeredOptions =
        Sets.newConcurrentHashSet();

    /** A cache storing a mapping from a given interface to its registration record. */
    private final Map<Class<? extends PipelineOptions>, Registration<?>> interfaceCache =
        Maps.newConcurrentMap();

    /** A cache storing a mapping from a set of interfaces to its registration record. */
    private final Map<Set<Class<? extends PipelineOptions>>, Registration<?>> combinedCache =
        Maps.newConcurrentMap();

View on GitHub (pinned to 12126d8942)

Solutions

  1. Provide a real value for the option or remove the flag entirely so defaults apply
  2. Change the option type to String (or a String collection) if empty is a legitimate state
  3. Check upstream env vars/variables feeding the argument list for empty expansions

Example fix

// before
--numWorkers=${NUM_WORKERS}   // NUM_WORKERS empty
// after
--numWorkers=${NUM_WORKERS:-4}
Defensive patterns

Strategy: validation

Validate before calling

String v = "--numWorkers=" + System.getenv().getOrDefault("NUM_WORKERS", "").trim();
if (v.endsWith("=")) throw new IllegalArgumentException("empty value for int option");

Try / catch

try { factory.fromArgs(args).as(Opts.class); } catch (IllegalArgumentException e) { /* supply defaults for empty args */ }

Prevention

When it happens

Trigger: Passing --someIntOption= or an empty JSON value for an Integer/long/complex-typed property via fromArgs or the options JSON map.

Common situations: Unset environment variable interpolated into --flag=${ENV} producing an empty value; template variables left blank; scripts building arg lists with missing defaults.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


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