apache/beam · error · IllegalArgumentException

input should be array, map, numeric or row

Error message

input should be array, map, numeric or row

What it means

Cast.castValue's switch handles ARRAY, MAP, ROW, and numeric input types; any other input type (e.g. STRING, BOOLEAN, DATETIME, primitive wrappers outside numeric) falls to the default and throws IllegalArgumentException because the default cast logic does not support it.

Source

Thrown at sdks/java/core/src/main/java/org/apache/beam/sdk/schemas/transforms/Cast.java:443

          Object outputKey =
              castValue(entry.getKey(), input.getMapKeyType(), output.getMapKeyType());
          Object outputValue =
              castValue(entry.getValue(), input.getMapValueType(), output.getMapValueType());

          outputMap.put(outputKey, outputValue);
        }

        return outputMap;

      default:
        if (inputType.equals(outputType)) {
          return inputValue;
        }

        if (inputType.isNumericType()) {
          return castNumber((Number) inputValue, inputType, outputType);
        } else {
          throw new IllegalArgumentException("input should be array, map, numeric or row");
        }
    }
  }
}

View on GitHub (pinned to 12126d8942)

Solutions

  1. Handle non-numeric scalar fields with an explicit Map/MapElements transform instead of Cast.
  2. Write a custom cast function: rows.apply(Cast.to(schema).withCastFunction(...)) or castRow with per-field functions.
  3. Check which fields are non-numeric scalars via input.getSchema() and either drop or transform them before casting.
  4. Upgrade Beam: support for more scalar types in castValue may have been added in later versions.

Example fix

// before (STRING field hits default branch)
rows.apply(Cast.to(outSchema));
// after: transform string field explicitly first
rows.apply(MapElements.into(TypeDescriptor.of(Row.class))
    .via(r -> convertStringFields(r))).apply(Cast.to(outSchema));
Defensive patterns

Strategy: validation

Validate before calling

for (Schema.Field f : inSchema.getFields()) {
  TypeName t = f.getType().getTypeName();
  boolean supported = EnumSet.of(TypeName.ARRAY, TypeName.MAP, TypeName.ROW).contains(t) || t.isNumericType();
  if (!supported) throw new IllegalStateException("field not castable: " + f.getName());
}

Type guard

static boolean castableByDefault(Schema.Field f) {
  TypeName t = f.getType().getTypeName();
  return t == TypeName.ARRAY || t == TypeName.MAP || t == TypeName.ROW || t.isNumericType();
}

Try / catch

try { rows.apply(Cast.to(outSchema)); } catch (IllegalArgumentException e) { if (e.getMessage().contains("array, map, numeric or row")) { /* route field through MapElements */ } else throw e; }

Prevention

When it happens

Trigger: Applying Cast.to(outputSchema) when a field has a scalar non-numeric input type such as STRING or BOOLEAN that the switch cannot dispatch on, even if the output type matches.

Common situations: Casting schemas containing string/boolean/datetime fields; users expecting Cast to be an arbitrary value converter when it only handles structural types and numbers.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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