apache/pulsar · error · IllegalArgumentException

Late data topic can be defined only when specifying a timest

Error message

Late data topic can be defined only when specifying a timestamp extractor class

What it means

A late-data topic lets the executor route records arriving after the watermark, but routing them correctly requires a custom timestamp extractor to know each record's event time. getWindowManager throws this IllegalArgumentException if lateDataTopic is set in WindowConfig while timestampExtractorClassName is null. The configuration is internally inconsistent, so initialization fails.

Source

Thrown at pulsar-functions/instance/src/main/java/org/apache/pulsar/functions/windowing/WindowFunctionExecutor.java:115

                WindowConfig.class);

        return windowConfig;
    }

    private WindowManager<Record<T>> getWindowManager(WindowConfig windowConfig, Context context) {

        WindowLifecycleListener<Event<Record<T>>> lifecycleListener = newWindowLifecycleListener(context);
        WindowManager<Record<T>> manager = new WindowManager<>(lifecycleListener, new ConcurrentLinkedQueue<>());

        if (this.windowConfig.getTimestampExtractorClassName() != null) {
            this.timestampExtractor = getTimeStampExtractor(windowConfig);

            waterMarkEventGenerator = new WaterMarkEventGenerator<>(manager, this.windowConfig
                    .getWatermarkEmitIntervalMs(),
                    this.windowConfig.getMaxLagMs(), new HashSet<>(context.getInputTopics()), context);
        } else {
            if (this.windowConfig.getLateDataTopic() != null) {
                throw new IllegalArgumentException(
                        "Late data topic can be defined only when specifying a timestamp extractor class");
            }
        }

        EvictionPolicy<Record<T>, ?> evictionPolicy = getEvictionPolicy(windowConfig);
        TriggerPolicy<Record<T>, ?> triggerPolicy = getTriggerPolicy(windowConfig, manager,
                evictionPolicy, context);
        manager.setEvictionPolicy(evictionPolicy);
        manager.setTriggerPolicy(triggerPolicy);

        return manager;
    }

    @SuppressWarnings("unchecked")
    private TimestampExtractor<T> getTimeStampExtractor(WindowConfig windowConfig) {

        Class<?> theCls;
        try {

View on GitHub (pinned to 820761864e)

Solutions

  1. Set timestampExtractorClassName in WindowConfig to a class implementing org.apache.pulsar.functions.api.windowing.TimestampExtractor
  2. Or remove lateDataTopic from WindowConfig if you don't need late-data routing (late events are then dropped by the eviction policy)
  3. Rebuild and redeploy the function with the corrected window config
  4. Document the extractor class and ensure its jar is bundled with the function

Example fix

// before
userConfig: { "windowConfig": { "windowLengthDurationMs": 60000, "lateDataTopic": "late-topic" } }
// after
userConfig: { "windowConfig": { "windowLengthDurationMs": 60000, "lateDataTopic": "late-topic",
  "timestampExtractorClassName": "com.example.MyTimestampExtractor" } }
Defensive patterns

Strategy: validation

Validate before calling

WindowConfig wc = ...;
if (wc.getLateDataTopic() != null && wc.getTimestampExtractorClassName() == null) {
    throw new IllegalArgumentException("lateDataTopic requires timestampExtractorClassName");
}

Try / catch

try {
    executor.initialize();
} catch (IllegalArgumentException e) {
    throw new IllegalStateException("inconsistent window config: " + e.getMessage(), e);
}

Prevention

When it happens

Trigger: WindowConfig supplied with lateDataTopic non-null but timestampExtractorClassName not set; typically a copy-pasted window config where the extractor class was removed or never added.

Common situations: Users enabling late-data handling for out-of-order events but relying on the default ingestion-time timestamps; config template stripping the extractor class name; switching from ingestion-time to event-time semantics without cleaning lateDataTopic.

Related errors


AI-assisted analysis of apache/pulsar@820761864e (2026-09-06). Data as JSON: /api/errors/4bd0b8aaac9043bf. Report an issue: GitHub.