apache/pulsar · error · IllegalArgumentException
Message retries not yet supported in Go function
Error message
Message retries not yet supported in Go function
What it means
Like the Python runtime, the Go function runtime does not implement message retries, so doGolangChecks rejects any Go function config with maxMessageRetries set to a non-negative value. This prevents deploying a Go function that silently ignores retry semantics.
Source
Thrown at pulsar-functions/utils/src/main/java/org/apache/pulsar/functions/utils/FunctionConfigUtils.java:775
throw new IllegalArgumentException("There is currently no support windowing in python");
}
if (functionConfig.getMaxMessageRetries() != null && functionConfig.getMaxMessageRetries() >= 0) {
throw new IllegalArgumentException("Message retries not yet supported in python");
}
}
private static void doGolangChecks(FunctionConfig functionConfig) {
if (functionConfig.getProcessingGuarantees() == FunctionConfig.ProcessingGuarantees.EFFECTIVELY_ONCE) {
throw new RuntimeException("Effectively-once processing guarantees not yet supported in Go function");
}
if (functionConfig.getWindowConfig() != null) {
throw new IllegalArgumentException("Windowing is not supported in Go function yet");
}
if (functionConfig.getMaxMessageRetries() != null && functionConfig.getMaxMessageRetries() >= 0) {
throw new IllegalArgumentException("Message retries not yet supported in Go function");
}
}
private static void verifyNoTopicClash(Collection<String> inputTopics, String outputTopic)
throws IllegalArgumentException {
if (inputTopics.contains(outputTopic)) {
throw new IllegalArgumentException(
String.format(
"Output topic %s is also being used as an input topic (topics must be one or the other)",
outputTopic));
}
}
public static void doCommonChecks(FunctionConfig functionConfig) {
if (isEmpty(functionConfig.getTenant())) {
throw new IllegalArgumentException("Function tenant cannot be null");
}
if (isEmpty(functionConfig.getNamespace())) {View on GitHub (pinned to 820761864e)
Solutions
- Remove maxMessageRetries (set to null) or omit --max-message-retries for the Go function
- Implement retry logic within the Go function (catch errors, retry with backoff, or republish to a retry/DLQ topic)
- Use the Java runtime if built-in message retries are required
Example fix
// before FunctionConfig config = new FunctionConfig(); config.setRuntime(FunctionConfig.Runtime.GO); config.setMaxMessageRetries(5); // after FunctionConfig config = new FunctionConfig(); config.setRuntime(FunctionConfig.Runtime.GO); config.setMaxMessageRetries(null); // retries unsupported in Go runtime
Defensive patterns
Strategy: validation
Validate before calling
if (config.getRuntime() == FunctionConfig.Runtime.GO
&& config.getMaxMessageRetries() != null
&& config.getMaxMessageRetries() >= 0) {
throw new IllegalArgumentException("maxMessageRetries is unsupported for Go functions; remove it");
}
FunctionConfigUtils.validateFunctionConfig(config, null); Type guard
boolean goRetriesAllowed(FunctionConfig c) {
return c.getRuntime() != FunctionConfig.Runtime.GO
|| c.getMaxMessageRetries() == null
|| c.getMaxMessageRetries() < 0;
} Try / catch
try {
FunctionConfigUtils.validateFunctionConfig(config, null);
} catch (IllegalArgumentException e) {
if (e.getMessage() != null && e.getMessage().contains("Message retries not yet supported in Go")) {
config.setMaxMessageRetries(null); // drop unsupported option for Go runtime
} else {
throw e;
}
} Prevention
- Keep retry settings out of Go and Python function configs
- Use runtime-specific deployment manifests rather than one shared FunctionConfig
- Implement retries in Go function code (backoff + DLQ topic) instead of maxMessageRetries
- Dry-run function create/update commands before production rollout
When it happens
Trigger: Creating or updating a Go function with setMaxMessageRetries(N) where N != null and N >= 0, or passing --max-message-retries with a --go function create/update command; validated via validateNonJavaFunction -> doGolangChecks.
Common situations: Uniform function-deployment pipelines that set retry counts for all runtimes; retry configs ported from Java functions to Go; operators enabling retries to survive transient processing failures in Go functions.
Related errors
- Effectively-once processing guarantees not yet supported in
- Windowing is not supported in Go function yet
- Message retries not yet supported in python
- MaxMessageRetries and Effectively once don't gel well
- Dead Letter Topic specified, however max retries is set to i
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/95d187c7f29fc229.
Report an issue: GitHub.