{"record":{"id":"d02c3e2e2a4bedd1","repo":"apache/pulsar","slug":"bookkeeper-ensemble-bookkeeper-write-quoru-d02c3e","errorCode":null,"errorMessage":"[--bookkeeper-ensemble], [--bookkeeper-write-quorum] and [--bookkeeper-ack-quorum] must greater than 0.","messagePattern":"\\[--bookkeeper-ensemble\\], \\[--bookkeeper-write-quorum\\] and \\[--bookkeeper-ack-quorum\\] must greater than 0\\.","errorType":"validation","errorClass":"ParameterException","httpStatus":null,"severity":"error","filePath":"pulsar-client-tools/src/main/java/org/apache/pulsar/admin/cli/CmdTopics.java","lineNumber":2176,"sourceCode":"        @Option(names = { \"-a\",\n                \"--bookkeeper-ack-quorum\" }, description = \"Number of acks (guaranteed copies) to wait for each entry\")\n        private int bookkeeperAckQuorum = 2;\n\n        @Option(names = { \"-r\",\n                \"--ml-mark-delete-max-rate\" }, description = \"Throttling rate of mark-delete operation \"\n                + \"(0 means no throttle, -1 means unset which will use the configuration from namespace or broker)\")\n        private double managedLedgerMaxMarkDeleteRate = -1;\n\n        @Option(names = { \"-c\",\n                \"--ml-storage-class\" },\n                description = \"Managed ledger storage class name\")\n        private String managedLedgerStorageClassName;\n\n        @Override\n        void run() throws PulsarAdminException {\n            String persistentTopic = validatePersistentTopic(topicName);\n            if (bookkeeperEnsemble <= 0 || bookkeeperWriteQuorum <= 0 || bookkeeperAckQuorum <= 0) {\n                throw new ParameterException(\"[--bookkeeper-ensemble], [--bookkeeper-write-quorum] \"\n                        + \"and [--bookkeeper-ack-quorum] must greater than 0.\");\n            }\n            getTopics().setPersistence(persistentTopic, new PersistencePolicies(bookkeeperEnsemble,\n                    bookkeeperWriteQuorum, bookkeeperAckQuorum, managedLedgerMaxMarkDeleteRate,\n                    managedLedgerStorageClassName));\n        }\n    }\n\n    @Command(description = \"Remove the persistence policy for a topic\", hidden = true)\n    private class RemovePersistence extends CliCommand {\n        @Parameters(description = \"persistent://tenant/namespace/topic\", arity = \"1\")\n        private String topicName;\n\n        @Override\n        void run() throws PulsarAdminException {\n            String persistentTopic = validatePersistentTopic(topicName);\n            getTopics().removePersistence(persistentTopic);\n        }","sourceCodeStart":2158,"sourceCodeEnd":2194,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-client-tools/src/main/java/org/apache/pulsar/admin/cli/CmdTopics.java#L2158-L2194","documentation":"The SetPersistence command requires the BookKeeper ensemble, write quorum, and ack quorum values to each be strictly positive before calling setPersistence. If any of --bookkeeper-ensemble, --bookkeeper-write-quorum, or --bookkeeper-ack-quorum is <= 0, it throws a ParameterException naming all three flags.","triggerScenarios":"Running `pulsar-admin topics set-persistence <topic>` with any of the three quorum flags set to 0 or a negative number.","commonSituations":"Zero-initialized variables in scripts; confusing 0 with 'use broker default' (it is not accepted here); setting write quorum greater than ensemble so values are later rejected server-side.","solutions":["Set all three flags to positive integers, e.g. `--bookkeeper-ensemble 3 --bookkeeper-write-quorum 3 --bookkeeper-ack-quorum 2`.","Ensure write quorum <= ensemble and ack quorum <= write quorum.","To revert to namespace defaults, use the remove-persistence command instead of zero values."],"exampleFix":"// before\nbin/pulsar-admin topics set-persistence my-topic --bookkeeper-ensemble 0 --bookkeeper-write-quorum 0 --bookkeeper-ack-quorum 0\n// after\nbin/pulsar-admin topics set-persistence my-topic --bookkeeper-ensemble 3 --bookkeeper-write-quorum 3 --bookkeeper-ack-quorum 2","handlingStrategy":"validation","validationCode":"// validate quorum relationships before invoking\nif [ \"$E\" -le 0 ] || [ \"$WQ\" -le 0 ] || [ \"$AQ\" -le 0 ]; then\n  echo \"ensemble/write-quorum/ack-quorum must be > 0\"; exit 1;\nfi\nif [ \"$WQ\" -gt \"$E\" ] || [ \"$AQ\" -gt \"$WQ\" ]; then\n  echo \"must satisfy ackQuorum <= writeQuorum <= ensemble\"; exit 1;\nfi","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Ensemble >= write quorum >= ack quorum >= 1 is the valid invariant.","Use remove-persistence to fall back to defaults instead of zeros.","Guard script variables against empty values defaulting to 0."],"tags":["cli","argument-validation","bookkeeper","persistence"],"backgroundTag":"invalid-argument-value","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"}