apache/pulsar · error · RuntimeException
Inconsistent types found between function input type and tim
Error message
Inconsistent types found between function input type and timestamp extractor type: function type = ${typeArgs0}, timestamp extractor type = ${timestampExtractorTypeArgs0} What it means
WindowFunctionExecutor.getTimeStampExtractor validates that the generic input type of the user's Function class (typeArgs[0]) matches the generic type of the user-provided TimestampExtractor. Apache Pulsar throws this RuntimeException at window setup when TypeResolver resolves the raw generic arguments and the two classes differ, because events would otherwise be fed to the extractor with the wrong type.
Source
Thrown at pulsar-functions/instance/src/main/java/org/apache/pulsar/functions/windowing/WindowFunctionExecutor.java:160
Object result;
try {
Constructor<?> constructor = theCls.getDeclaredConstructor();
constructor.setAccessible(true);
result = constructor.newInstance();
} catch (InstantiationException ie) {
throw new RuntimeException("User class must be concrete", ie);
} catch (NoSuchMethodException e) {
throw new RuntimeException("User class doesn't have such method", e);
} catch (IllegalAccessException e) {
throw new RuntimeException("User class must have a no-arg constructor", e);
} catch (InvocationTargetException e) {
throw new RuntimeException("User class constructor throws exception", e);
}
Class<?>[] timestampExtractorTypeArgs = TypeResolver.resolveRawArguments(
TimestampExtractor.class, result.getClass());
Class<?>[] typeArgs = TypeResolver.resolveRawArguments(Function.class, this.getClass());
if (!typeArgs[0].equals(timestampExtractorTypeArgs[0])) {
throw new RuntimeException(
"Inconsistent types found between function input type and timestamp extractor type: "
+ " function type = " + typeArgs[0] + ", timestamp extractor type = "
+ timestampExtractorTypeArgs[0]);
}
return (TimestampExtractor<T>) result;
}
private TriggerPolicy<Record<T>, ?> getTriggerPolicy(WindowConfig windowConfig, WindowManager<Record<T>> manager,
EvictionPolicy<Record<T>, ?> evictionPolicy, Context context) {
if (windowConfig.getSlidingIntervalCount() != null) {
if (this.isEventTime()) {
return new WatermarkCountTriggerPolicy<>(
windowConfig.getSlidingIntervalCount(), manager, evictionPolicy, manager);
} else {
return new CountTriggerPolicy<>(windowConfig.getSlidingIntervalCount(), manager, evictionPolicy);
}
} else {
if (this.isEventTime()) {View on GitHub (pinned to 820761864e)
Solutions
- Make the TimestampExtractor's generic parameter exactly match the Function's input type parameter.
- Check the resolved classes by logging typeArgs[0] and timestampExtractorTypeArgs[0] and aligning the generics.
- If a raw type was intended, parameterize both classes explicitly instead of relying on raw types.
Example fix
// before
public class MyFunction implements Function<String, Void> { ... }
public class MyExtractor implements TimestampExtractor<Long> { ... }
// after
public class MyFunction implements Function<String, Void> { ... }
public class MyExtractor implements TimestampExtractor<String> { ... } Defensive patterns
Strategy: validation
Validate before calling
Class<?>[] typeArgs = TypeResolver.resolveRawArguments(Function.class, fnClass);
Class<?>[] teArgs = TypeResolver.resolveRawArguments(TimestampExtractor.class, extractorClass);
if (!typeArgs[0].equals(teArgs[0])) {
throw new IllegalStateException("Function input " + typeArgs[0] + " != extractor type " + teArgs[0]);
} Type guard
static <F, E> boolean typesMatch(Class<? extends Function<F, ?>> fn, Class<? extends TimestampExtractor<E>> te) {
return TypeResolver.resolveRawArguments(Function.class, fn)[0]
.equals(TypeResolver.resolveRawArguments(TimestampExtractor.class, te)[0]);
} Prevention
- Always parameterize Function and TimestampExtractor with the same concrete type.
- Unit-test window setup early to surface generic mismatches at deploy time.
- Avoid raw types; enable -Xlint:rawtypes.
When it happens
Trigger: Registering a TimestampExtractor whose generic parameter does not equal the Function's input generic, e.g. Function<String, ...> paired with TimestampExtractor<Long>, or leaving the extractor's type parameter untyped so resolution yields Object or a raw type.
Common situations: Copy-pasting a sample TimestampExtractor into a function with a different input POJO; refactoring the function input type without updating the extractor; using a raw (non-generic) extractor class that resolves to the wrong raw argument.
Related errors
- Not implemented
- Serializer type mismatch
- Serializer type mismatch ${typeArg} vs ${serDeTypeArg}
- Window length is not specified
- Window length for time and count are set! Please set one or
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/bddcd56871be5d4e.
Report an issue: GitHub.