{"record":{"id":"d0822d93f4963933","repo":"apache/pulsar","slug":"timeout-must-be-0","errorCode":null,"errorMessage":"timeout must be > 0","messagePattern":"timeout must be > 0","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"pulsar-client-api-v5/src/main/java/org/apache/pulsar/client/api/v5/config/TransactionPolicy.java","lineNumber":40,"sourceCode":"import java.util.Objects;\nimport lombok.EqualsAndHashCode;\nimport lombok.ToString;\n\n/**\n * Transaction configuration for the Pulsar client.\n *\n * <p>Construct via {@link #builder()}.\n */\n@EqualsAndHashCode\n@ToString\npublic final class TransactionPolicy {\n\n    private final Duration timeout;\n\n    private TransactionPolicy(Duration timeout) {\n        Objects.requireNonNull(timeout, \"timeout must not be null\");\n        if (timeout.isNegative() || timeout.isZero()) {\n            throw new IllegalArgumentException(\"timeout must be > 0\");\n        }\n        this.timeout = timeout;\n    }\n\n    /**\n     * @return transaction timeout — if the transaction is not committed or aborted within this duration,\n     *         the broker automatically aborts it\n     */\n    public Duration timeout() {\n        return timeout;\n    }\n\n    /**\n     * @return a new builder for constructing a {@link TransactionPolicy}\n     */\n    public static Builder builder() {\n        return new Builder();\n    }","sourceCodeStart":22,"sourceCodeEnd":58,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-client-api-v5/src/main/java/org/apache/pulsar/client/api/v5/config/TransactionPolicy.java#L22-L58","documentation":"TransactionPolicy requires a strictly positive Duration for the transaction timeout. The timeout determines how long a transaction may remain open before the coordinator aborts it; null, zero, or negative values cannot define a valid deadline, so the private constructor throws IllegalArgumentException (null is caught by the preceding requireNonNull).","triggerScenarios":"Passing Duration.ZERO or a negative Duration to TransactionPolicy's builder/factory; passing null produces the preceding 'timeout must not be null' NPE instead.","commonSituations":"Config values parsed as 0 (unset property defaulting to 0 seconds), or code computing a timeout that rounds down to zero.","solutions":["Pass a positive duration, e.g. .timeout(Duration.ofMinutes(1)) on the TransactionPolicy builder","If the value comes from config, default to a positive constant when it is missing or <= 0","Confirm the configured seconds/minutes value is > 0 before wrapping it in a Duration"],"exampleFix":"// before\nlong seconds = config.getProperty(\"txn.timeout\", 0);\nTransactionPolicy p = TransactionPolicy.builder().timeout(Duration.ofSeconds(seconds)).build();\n// after\nlong seconds = config.getProperty(\"txn.timeout\", 60);\nif (seconds <= 0) seconds = 60;\nTransactionPolicy p = TransactionPolicy.builder().timeout(Duration.ofSeconds(seconds)).build();","handlingStrategy":"validation","validationCode":"if (timeout == null || timeout.isNegative() || timeout.isZero()) {\n    throw new IllegalArgumentException(\"transaction timeout must be a positive Duration, got: \" + timeout);\n}","typeGuard":"boolean isPositive(Duration d) { return d != null && !d.isZero() && !d.isNegative(); }","tryCatchPattern":"try {\n    policy = TransactionPolicy.builder().timeout(timeout).build();\n} catch (IllegalArgumentException e) {\n    log.error(\"Invalid transaction timeout: {}\", e.getMessage());\n    policy = TransactionPolicy.builder().timeout(Duration.ofMinutes(1)).build();\n}","preventionTips":["Never let a config default of 0 flow into a Duration-based timeout","Clamp parsed values: Math.max(1, configuredSeconds)","Document that zero means invalid for transaction timeouts (unlike ProcessingTimeoutPolicy)"],"tags":["java","validation","transactions","duration"],"backgroundTag":"invalid-duration-value","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"}