{"record":{"id":"5db1481996bf0707","repo":"apache/pulsar","slug":"reconsumelater-method-not-supported-because-retrye","errorCode":null,"errorMessage":"reconsumeLater method not supported because retryEnabled is set to false. You can enable it via ConsumerBuilder.","messagePattern":"reconsumeLater method not supported because retryEnabled is set to false\\. You can enable it via ConsumerBuilder\\.","errorType":"exception","errorClass":"PulsarClientException","httpStatus":null,"severity":"error","filePath":"pulsar-client/src/main/java/org/apache/pulsar/client/impl/ConsumerBase.java","lineNumber":509,"sourceCode":"            acknowledgeAsync(messages).get();\n        } catch (InterruptedException e) {\n            Thread.currentThread().interrupt();\n            throw PulsarClientException.unwrap(e);\n        } catch (ExecutionException e) {\n            throw PulsarClientException.unwrap(e);\n        }\n    }\n\n    @Override\n    public void reconsumeLater(Message<?> message, long delayTime, TimeUnit unit) throws PulsarClientException {\n        reconsumeLater(message, null, delayTime, unit);\n    }\n\n    @Override\n    public void reconsumeLater(Message<?> message, Map<String, String> customProperties, long delayTime, TimeUnit unit)\n            throws PulsarClientException {\n        if (!conf.isRetryEnable()) {\n            throw new PulsarClientException(RECONSUME_LATER_ERROR_MSG);\n        }\n        try {\n            reconsumeLaterAsync(message, customProperties, delayTime, unit).get();\n        } catch (InterruptedException e) {\n            Thread.currentThread().interrupt();\n            throw PulsarClientException.unwrap(e);\n        } catch (ExecutionException e) {\n            throw PulsarClientException.unwrap(e);\n        }\n    }\n\n    @Override\n    public void reconsumeLater(Messages<?> messages, long delayTime, TimeUnit unit) throws PulsarClientException {\n        try {\n            reconsumeLaterAsync(messages, delayTime, unit).get();\n        } catch (InterruptedException e) {\n            Thread.currentThread().interrupt();\n            throw PulsarClientException.unwrap(e);","sourceCodeStart":491,"sourceCodeEnd":527,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-client/src/main/java/org/apache/pulsar/client/impl/ConsumerBase.java#L491-L527","documentation":"reconsumeLater() delivers a message back to the retry-letter topic for redelivery with optional delay; this only works when the subscription was created with retryEnabled (dead-letter/retry machinery on the subscription). ConsumerBase.reconsumeLater checks conf.isRetryEnable() and throws a PulsarClientException with RECONSUME_LATER_ERROR_MSG when retry is disabled, because without the retry topic there is nowhere to re-publish the message.","triggerScenarios":"Calling consumer.reconsumeLater(message, customProperties, delayTime, unit) (or the 2-arg overload) on a consumer whose ConsumerBuilder did not call enableRetry(true). The async variant reconsumeLaterAsync fails with the same message.","commonSituations":"Adding retry semantics to an existing subscription after the fact without recreating it with enableRetry; assuming reconsumeLater works on any subscription type; forgetting that retry requires a shared subscription and a retryLetterTopic configuration for full function.","solutions":["Add .enableRetry(true) to the ConsumerBuilder before subscribing (requires a non-exclusive/shared subscription)","Set a retry letter topic via deadLetterPolicy if you want a custom retry topic, otherwise the default <topic>-RETRY is used","Recreate the consumer/subscription — retry enablement is fixed at subscription creation","Use negativeAcknowledge() or acknowledge with dead-letter policy as an alternative for redelivery"],"exampleFix":"// before\nConsumer<String> c = client.newConsumer(Schema.STRING)\n    .topic(\"t\").subscriptionName(\"s\")\n    .subscriptionType(SubscriptionType.Shared)\n    .subscribe();\nc.reconsumeLater(msg, 10, TimeUnit.SECONDS); // throws\n// after\nConsumer<String> c = client.newConsumer(Schema.STRING)\n    .topic(\"t\").subscriptionName(\"s\")\n    .subscriptionType(SubscriptionType.Shared)\n    .enableRetry(true)\n    .subscribe();\nc.reconsumeLater(msg, 10, TimeUnit.SECONDS);","handlingStrategy":"validation","validationCode":"// at consumer creation:\nConsumer<T> c = client.newConsumer(schema)\n    .topic(topic).subscriptionName(sub)\n    .subscriptionType(SubscriptionType.Shared)\n    .enableRetry(true)\n    .subscribe();\n// keep retryEnabled flag alongside the consumer reference\nif (!retryEnabled) {\n    throw new IllegalStateException(\"reconsumeLater requires enableRetry(true)\");\n}","typeGuard":"boolean supportsReconsumeLater(org.apache.pulsar.client.api.Consumer<T> c) {\n    return ((ConsumerBase<T>) c).getConf().isRetryEnable();\n}","tryCatchPattern":"try {\n    consumer.reconsumeLater(msg, 10, TimeUnit.SECONDS);\n} catch (PulsarClientException e) {\n    if (String.valueOf(e.getMessage()).contains(\"retryEnabled\")) {\n        consumer.negativeAcknowledge(msg); // fallback redelivery\n    }\n}","preventionTips":["Call .enableRetry(true) on every builder whose consumers may use reconsumeLater","Remember retry requires Shared/Key_Shared subscription type (not Exclusive/Failover)","Consider negativeAcknowledge() as a simpler redelivery mechanism when retry topics are unnecessary"],"tags":["pulsar","retry","configuration","reconsume-later"],"backgroundTag":"retry-not-enabled","analyzedSha":"820761864ed8e2a7d2e52dd9763ad2ae117c1395","analyzedAt":"2026-09-06T00:14:20.138Z","contentChangedAt":"2026-09-06T00:14:20.138Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}