{"record":{"id":"d8bff5a80d1c5115","repo":"apache/pulsar","slug":"effectively-once-processing-guarantees-not-yet-sup-d8bff5","errorCode":null,"errorMessage":"Effectively-once processing guarantees not yet supported in Go function","messagePattern":"Effectively-once processing guarantees not yet supported in Go function","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"pulsar-functions/utils/src/main/java/org/apache/pulsar/functions/utils/FunctionConfigUtils.java","lineNumber":767,"sourceCode":"    }\n\n    private static void doPythonChecks(FunctionConfig functionConfig) {\n        if (functionConfig.getProcessingGuarantees() == FunctionConfig.ProcessingGuarantees.EFFECTIVELY_ONCE) {\n            throw new RuntimeException(\"Effectively-once processing guarantees not yet supported in Python\");\n        }\n\n        if (functionConfig.getWindowConfig() != null) {\n            throw new IllegalArgumentException(\"There is currently no support windowing in python\");\n        }\n\n        if (functionConfig.getMaxMessageRetries() != null && functionConfig.getMaxMessageRetries() >= 0) {\n            throw new IllegalArgumentException(\"Message retries not yet supported in python\");\n        }\n    }\n\n    private static void doGolangChecks(FunctionConfig functionConfig) {\n        if (functionConfig.getProcessingGuarantees() == FunctionConfig.ProcessingGuarantees.EFFECTIVELY_ONCE) {\n            throw new RuntimeException(\"Effectively-once processing guarantees not yet supported in Go function\");\n        }\n\n        if (functionConfig.getWindowConfig() != null) {\n            throw new IllegalArgumentException(\"Windowing is not supported in Go function yet\");\n        }\n\n        if (functionConfig.getMaxMessageRetries() != null && functionConfig.getMaxMessageRetries() >= 0) {\n            throw new IllegalArgumentException(\"Message retries not yet supported in Go function\");\n        }\n    }\n\n    private static void verifyNoTopicClash(Collection<String> inputTopics, String outputTopic)\n            throws IllegalArgumentException {\n        if (inputTopics.contains(outputTopic)) {\n            throw new IllegalArgumentException(\n                    String.format(\n                            \"Output topic %s is also being used as an input topic (topics must be one or the other)\",\n                            outputTopic));","sourceCodeStart":749,"sourceCodeEnd":785,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-functions/utils/src/main/java/org/apache/pulsar/functions/utils/FunctionConfigUtils.java#L749-L785","documentation":"The Go function runtime does not support EFFECTIVELY_ONCE processing guarantees, so doGolangChecks rejects any Go function config requesting that mode. Effectively-once requires deduplication/ack semantics the Go runtime has not implemented, and the check prevents silently downgrading the guarantee.","triggerScenarios":"Creating or updating a Go function with setProcessingGuarantees(FunctionConfig.ProcessingGuarantees.EFFECTIVELY_ONCE) (or --processing-guarantees EFFECTIVELY_ONCE on the CLI for a --go function), which flows through validateNonJavaFunction -> doGolangChecks.","commonSituations":"Reusing a config that worked for a Java function (which supports effectively-once) for a Go function; strict-delivery requirements copied into Go-based deployments; CI templates that set EFFECTIVELY_ONCE globally.","solutions":["Set processingGuarantees to ATLEAST_ONCE (or ATMOST_ONCE) for the Go function","Implement idempotent processing in the Go function (dedupe by message id/key on the output side)","Enable topic-level producer deduplication on the output topic as a partial effectively-once substitute","Move the function to the Java runtime if EFFECTIVELY_ONCE is mandatory"],"exampleFix":"// before\nFunctionConfig config = new FunctionConfig();\nconfig.setRuntime(FunctionConfig.Runtime.GO);\nconfig.setProcessingGuarantees(FunctionConfig.ProcessingGuarantees.EFFECTIVELY_ONCE);\n\n// after\nFunctionConfig config = new FunctionConfig();\nconfig.setRuntime(FunctionConfig.Runtime.GO);\nconfig.setProcessingGuarantees(FunctionConfig.ProcessingGuarantees.ATLEAST_ONCE);","handlingStrategy":"validation","validationCode":"if (config.getRuntime() == FunctionConfig.Runtime.GO\n        && config.getProcessingGuarantees() == FunctionConfig.ProcessingGuarantees.EFFECTIVELY_ONCE) {\n    throw new IllegalArgumentException(\"EFFECTIVELY_ONCE is unsupported for Go functions\");\n}\nFunctionConfigUtils.validateFunctionConfig(config, null);","typeGuard":"boolean goProcessingGuaranteeSupported(FunctionConfig c) {\n    return c.getRuntime() != FunctionConfig.Runtime.GO\n        || c.getProcessingGuarantees() != FunctionConfig.ProcessingGuarantees.EFFECTIVELY_ONCE;\n}","tryCatchPattern":"try {\n    FunctionConfigUtils.validateFunctionConfig(config, null);\n} catch (RuntimeException e) {\n    if (e.getMessage() != null && e.getMessage().contains(\"Effectively-once processing guarantees not yet supported in Go\")) {\n        config.setProcessingGuarantees(FunctionConfig.ProcessingGuarantees.ATLEAST_ONCE); // degrade explicitly\n    } else {\n        throw e;\n    }\n}","preventionTips":["Default Go/Python functions to ATLEAST_ONCE; only use EFFECTIVELY_ONCE with the Java runtime","Document delivery-guarantee support per runtime in your platform's function templates","Add a pre-deploy validation step that rejects EFFECTIVELY_ONCE for non-Java runtimes","If effectively-once semantics are required, implement idempotency in function code rather than relying on the runtime"],"tags":["pulsar-functions","go-runtime","processing-guarantees","unsupported-feature"],"backgroundTag":"unsupported-feature-for-runtime","analyzedSha":"820761864ed8e2a7d2e52dd9763ad2ae117c1395","analyzedAt":"2026-09-06T00:14:20.138Z","contentChangedAt":"2026-09-06T00:14:20.138Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}