apache/pulsar · error · IllegalArgumentException

Windows Function not support delivery semantics.

Error message

Windows Function not support  delivery semantics.

What it means

Pulsar Functions windowing only supports certain delivery semantics. When a WindowConfig is present, convert() rejects EFFECTIVELY_ONCE and MANUAL processing guarantees with this IllegalArgumentException ('Windows Function not support <X> delivery semantics'), because the windowing implementation cannot provide them.

Source

Thrown at pulsar-functions/utils/src/main/java/org/apache/pulsar/functions/utils/FunctionConfigUtils.java:323

            RetryDetails retryDetails = functionDetails.setRetryDetails();
            retryDetails.setMaxMessageRetries(functionConfig.getMaxMessageRetries());
            if (isNotEmpty(functionConfig.getDeadLetterTopic())) {
                retryDetails.setDeadLetterTopic(functionConfig.getDeadLetterTopic());
            }
        }

        Map<String, Object> configs = new HashMap<>();
        if (functionConfig.getUserConfig() != null) {
            configs.putAll(functionConfig.getUserConfig());
        }

        // windowing related
        WindowConfig windowConfig = functionConfig.getWindowConfig();
        if (windowConfig != null) {
            // Windows Function not support MANUAL and EFFECTIVELY_ONCE.
            if (functionConfig.getProcessingGuarantees() == FunctionConfig.ProcessingGuarantees.EFFECTIVELY_ONCE
                    || functionConfig.getProcessingGuarantees() == FunctionConfig.ProcessingGuarantees.MANUAL) {
                throw new IllegalArgumentException(
                        "Windows Function not support "
                                + functionConfig.getProcessingGuarantees() + " delivery semantics.");
            } else {
                // Override functionConfig.getProcessingGuarantees to MANUAL, and set windowsFunction is guarantees
                windowConfig.setProcessingGuarantees(WindowConfig.ProcessingGuarantees
                        .valueOf(functionDetails.getProcessingGuarantees().name()));
                functionDetails.setProcessingGuarantees(ProcessingGuarantees.MANUAL);
            }
            windowConfig.setActualWindowFunctionClassName(extractedDetails.getFunctionClassName());
            configs.put(WindowConfig.WINDOW_CONFIG_KEY, windowConfig);
            // set class name to window function executor
            functionDetails.setClassName("org.apache.pulsar.functions.windowing.WindowFunctionExecutor");
        } else {
            if (extractedDetails.getFunctionClassName() != null) {
                functionDetails.setClassName(extractedDetails.getFunctionClassName());
            }
        }
        if (!configs.isEmpty()) {

View on GitHub (pinned to 820761864e)

Solutions

  1. Remove the windowConfig if you require EFFECTIVELY_ONCE processing guarantees
  2. Set processingGuarantees to ATLEAST_ONCE or ATMOST_ONCE for windowed functions
  3. If MANUAL was set implicitly, explicitly set a supported guarantee before submitting the windowed function
  4. Use non-windowed function logic plus external deduplication if exactly-once semantics are mandatory

Example fix

// before
cfg.setWindowConfig(new WindowConfig());
cfg.setProcessingGuarantees(FunctionConfig.ProcessingGuarantees.EFFECTIVELY_ONCE); // throws
// after
cfg.setWindowConfig(new WindowConfig());
cfg.setProcessingGuarantees(FunctionConfig.ProcessingGuarantees.ATLEAST_ONCE); // supported for windowing
Defensive patterns

Strategy: validation

Validate before calling

// Pre-validate windowing + guarantee combination
if (cfg.getWindowConfig() != null
    && (cfg.getProcessingGuarantees() == FunctionConfig.ProcessingGuarantees.EFFECTIVELY_ONCE
        || cfg.getProcessingGuarantees() == FunctionConfig.ProcessingGuarantees.MANUAL)) {
  throw new IllegalArgumentException("Windowed functions require ATLEAST_ONCE or ATMOST_ONCE");
}

Try / catch

try {
  FunctionDetails d = FunctionConfigUtils.convert(cfg, pkg);
} catch (IllegalArgumentException e) {
  if (e.getMessage() != null && e.getMessage().startsWith("Windows Function not support")) {
    cfg.setProcessingGuarantees(FunctionConfig.ProcessingGuarantees.ATLEAST_ONCE);
    d = FunctionConfigUtils.convert(cfg, pkg); // retry with supported guarantee
  } else {
    throw e;
  }
}

Prevention

When it happens

Trigger: Submitting a function whose FunctionConfig has both a non-null windowConfig and processingGuarantees set to EFFECTIVELY_ONCE (or MANUAL) — e.g. a windowed function created with --processing-guarantees EFFECTIVELY_ONCE via the CLI or REST API.

Common situations: Developers adding at-least-once/effectively-once guarantees to an existing windowed function assuming all guarantees are supported; copy-pasted function configs combining windowing with effectively-once; migration scripts setting guarantees globally for all functions including windowed ones.

Related errors


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