{"record":{"id":"aadd75a7b9774046","repo":"apache/pulsar","slug":"timeout-must-not-be-negative","errorCode":null,"errorMessage":"timeout must not be negative","messagePattern":"timeout must not be negative","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"pulsar-client-api-v5/src/main/java/org/apache/pulsar/client/api/v5/config/ProcessingTimeoutPolicy.java","lineNumber":56,"sourceCode":" * when the application's processing time is bounded and you want stalled deliveries to\n * be reattempted automatically.\n *\n * <p>Use {@link #of(Duration)} for the common case (no extra backoff), or\n * {@link #builder()} to also configure {@code redeliveryBackoff}.\n */\n@EqualsAndHashCode\n@ToString\npublic final class ProcessingTimeoutPolicy {\n\n    private final Duration timeout;\n    private final BackoffPolicy redeliveryBackoff;\n\n    private ProcessingTimeoutPolicy(Duration timeout, BackoffPolicy redeliveryBackoff) {\n        if (timeout == null) {\n            throw new IllegalArgumentException(\"timeout must not be null\");\n        }\n        if (timeout.isNegative()) {\n            throw new IllegalArgumentException(\"timeout must not be negative\");\n        }\n        this.timeout = timeout;\n        this.redeliveryBackoff = redeliveryBackoff;\n    }\n\n    /**\n     * @return how long the client waits for the application to ack a delivery before\n     *         requesting redelivery; {@link Duration#ZERO} disables\n     */\n    public Duration timeout() {\n        return timeout;\n    }\n\n    /**\n     * @return optional backoff applied between redeliveries, or {@code null} for the\n     *         default (no extra delay)\n     */\n    public BackoffPolicy redeliveryBackoff() {","sourceCodeStart":38,"sourceCodeEnd":74,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-client-api-v5/src/main/java/org/apache/pulsar/client/api/v5/config/ProcessingTimeoutPolicy.java#L38-L74","documentation":"ProcessingTimeoutPolicy rejects a negative Duration in its private constructor. A negative processing timeout is meaningless — it would represent a deadline already in the past — so the library fails fast with IllegalArgumentException instead of producing undefined redelivery behavior.","triggerScenarios":"Passing a negative Duration (e.g. Duration.ofSeconds(-1), Duration.ofMillis(negativeValue)) to ProcessingTimeoutPolicy.builder().timeout(...) or the of() factory.","commonSituations":"Arithmetic on Durations producing negative results (earlier time minus later time), or misconfigured config values parsed as negative numbers and wrapped in Duration.of*().","solutions":["Pass a non-negative Duration; use Duration.ZERO if 'no timeout' is intended (zero is explicitly allowed)","Guard the value before building: if (d.isNegative()) throw new IllegalArgumentException(...) or clamp with a default"],"exampleFix":"// before\nDuration timeout = Duration.between(lastSeen, Instant.now()); // can be negative\nProcessingTimeoutPolicy p = ProcessingTimeoutPolicy.builder().timeout(timeout).build();\n// after\nDuration timeout = Duration.between(lastSeen, Instant.now());\nif (timeout.isNegative()) timeout = Duration.ZERO;\nProcessingTimeoutPolicy p = ProcessingTimeoutPolicy.builder().timeout(timeout).build();","handlingStrategy":"validation","validationCode":"if (timeout != null && timeout.isNegative()) {\n    throw new IllegalArgumentException(\"processing timeout must be non-negative, got: \" + timeout);\n}","typeGuard":"boolean isNonNegative(Duration d) { return d != null && !d.isNegative(); }","tryCatchPattern":"try {\n    policy = ProcessingTimeoutPolicy.builder().timeout(timeout).build();\n} catch (IllegalArgumentException e) {\n    log.warn(\"Negative timeout rejected, falling back to default\");\n    policy = ProcessingTimeoutPolicy.builder().timeout(Duration.ofSeconds(30)).build();\n}","preventionTips":["Never compute a Duration by subtracting timestamps without clamping to zero","Reject or clamp negative values at the config-parsing layer","Remember Duration.ZERO is allowed; negatives are not"],"tags":["java","validation","duration","client-config"],"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"}