apache/beam · error · ClassCastException
Value is not valid for DisplayData type %s: %s
Error message
Value is not valid for DisplayData type %s: %s
What it means
DisplayData.item()/named() value helpers call checkType() to assert the runtime value matches the DisplayData.Type it is being registered as (e.g. a Java class registered as DisplayData.Type.CLASS). If value.getClass() is not assignable to the expected class, a ClassCastException is thrown with this message. It indicates the wrong display-data registration method was used for the value's type.
Source
Thrown at sdks/java/core/src/main/java/org/apache/beam/sdk/transforms/display/DisplayData.java:627
},
DURATION {
@Override
FormattedItemValue format(Object value) {
Duration duration = checkType(value, Duration.class, DURATION);
return new FormattedItemValue(duration.getMillis());
}
},
JAVA_CLASS {
@Override
FormattedItemValue format(Object value) {
Class<?> clazz = checkType(value, Class.class, JAVA_CLASS);
return new FormattedItemValue(clazz.getName(), ReflectHelpers.getSimpleName(clazz));
}
};
private static <T> T checkType(Object value, Class<T> clazz, DisplayData.Type expectedType) {
if (!clazz.isAssignableFrom(value.getClass())) {
throw new ClassCastException(
String.format("Value is not valid for DisplayData type %s: %s", expectedType, value));
}
@SuppressWarnings("unchecked") // type checked above.
T typedValue = (T) value;
return typedValue;
}
/**
* Format the display data value into a long string representation, and optionally a shorter
* representation for display.
*
* <p>Internal-only. Value objects can be safely cast to the expected Java type.
*/
abstract FormattedItemValue format(Object value);
/**
* Safe version of {@link Type#format(Object)}, which checks for null input value and if soView on GitHub (pinned to 12126d8942)
Solutions
- Match the registration method to the value type (item(String) for strings, instant(Instant), duration(Duration/ReadableDuration), etc.)
- Convert the value before registering (e.g. value.toString() if you want it as a STRING item)
- Update populateDisplayData after changing field types
- Catch ClassCastException in test harnesses that exercise populateDisplayData to catch mismatches in unit tests
Example fix
// before
builder.add(DisplayData.item("deadline", DisplayData.Type.INSTANT, "2024-01-01T00:00:00Z")); // String
// after
builder.add(DisplayData.item("deadline", DisplayData.Type.INSTANT, Instant.parse("2024-01-01T00:00:00Z"))); Defensive patterns
Strategy: type-guard
Validate before calling
if (!(value instanceof Instant)) { throw new IllegalArgumentException("instant() requires an Instant"); } Type guard
static <T> boolean isAssignable(Object value, Class<T> clazz) { return value != null && clazz.isAssignableFrom(value.getClass()); } Try / catch
try { builder.add(DisplayData.item(key, DisplayData.Type.INSTANT, value)); } catch (ClassCastException e) { /* register as STRING via toString() instead */ } Prevention
- Match DisplayData registration helpers to exact value types
- Add a unit test invoking populateDisplayData for every transform
- Convert mismatched values with toString()/parsing before registration
When it happens
Trigger: In a DoFn/transform's populateDisplayData(builder), calling e.g. DisplayData.instant(value) or DisplayData.duration(value) or clazz-registration with an object of the wrong runtime type — e.g. passing a String where an Instant is required, or a non-Class object where a Class is expected.
Common situations: Refactoring a transform's field types without updating populateDisplayData; copy-pasting display data registration lines between transforms; passing boxed types vs primitives mismatch.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- Unable to provide coder for %s, this factory can only provid
- The input schema must have exactly one field of type byte.
- Cannot merge two types: +fieldType1.getTypeName()+ and +fiel
- value type is '%s' for field type '%s'
- Specified path '%s' already used for subcomponent %s. Subcom
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/4b108f7c3a779642.
Report an issue: GitHub.