{"record":{"id":"e686212dd92f055d","repo":"apache/pulsar","slug":"bookkeeper-ensemble-bookkeeper-write-quoru","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/CmdNamespaces.java","lineNumber":1419,"sourceCode":"                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\" },\n                description = \"Throttling rate of mark-delete operation \"\n                        + \"(0 means no throttle, -1 means unset which will use the default configuration from 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 namespace = validateNamespace(namespaceName);\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            getAdmin().namespaces().setPersistence(namespace, new PersistencePolicies(bookkeeperEnsemble,\n                    bookkeeperWriteQuorum, bookkeeperAckQuorum, managedLedgerMaxMarkDeleteRate,\n                    managedLedgerStorageClassName));\n        }\n    }\n\n    @Command(description = \"Clear backlog for a namespace\")\n    private class ClearBacklog extends CliCommand {\n        @Parameters(description = \"tenant/namespace\", arity = \"1\")\n        private String namespaceName;\n\n        @Option(names = { \"--sub\", \"-s\" }, description = \"subscription name\")\n        private String subscription;\n\n        @Option(names = { \"--bundle\", \"-b\" }, description = \"{start-boundary}_{end-boundary}\")\n        private String bundle;","sourceCodeStart":1401,"sourceCodeEnd":1437,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-client-tools/src/main/java/org/apache/pulsar/admin/cli/CmdNamespaces.java#L1401-L1437","documentation":"The set-persistence command validates that bookkeeper ensemble, write quorum, and ack quorum are all positive before building PersistencePolicies. A value <= 0 for any of --bookkeeper-ensemble, --bookkeeper-write-quorum, or --bookkeeper-ack-quorum would create an invalid replication configuration, so the CLI throws this ParameterException.","triggerScenarios":"Running `pulsar-admin namespaces set-persistence <ns> --bookkeeper-ensemble N --bookkeeper-write-quorum N --bookkeeper-ack-quorum N ...` where any of the three values is 0 or negative.","commonSituations":"Variables defaulting to 0 in shell scripts when unset (e.g. ${E:-0}); misunderstanding quorum semantics and setting write/ack quorum to 0 to 'disable'; templating bugs that leave a flag at its zero default.","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 for a valid policy","Fix the script/template so unset variables don't default to 0"],"exampleFix":"// before\nENSEMBLE=0  # unset variable defaulted to 0\npulsar-admin namespaces set-persistence my-tenant/my-ns -e $ENSEMBLE -w 3 -a 2\n// after\nENSEMBLE=3\npulsar-admin namespaces set-persistence my-tenant/my-ns -e $ENSEMBLE -w 3 -a 2","handlingStrategy":"validation","validationCode":"// shell guard\nif [ \"$ENSEMBLE\" -le 0 ] || [ \"$WRITE_Q\" -le 0 ] || [ \"$ACK_Q\" -le 0 ]; then\n  echo \"ensemble/write-quorum/ack-quorum must be > 0\" >&2; exit 1;\nfi","typeGuard":"// pseudo: validate positive policy numbers\nboolean valid = ensemble > 0 && writeQuorum > 0 && ackQuorum > 0\n             && writeQuorum <= ensemble && ackQuorum <= writeQuorum;","tryCatchPattern":"try {\n    admin.namespaces().setPersistence(ns, policies);\n} catch (IllegalArgumentException e) {\n    // sanitize defaults and retry with valid positive values\n}","preventionTips":["Use strict shell defaults (${VAR:?}) so unset vars fail instead of becoming 0","Respect the ordering ensemble >= write-quorum >= ack-quorum","Sanity-check policies with a dry run on a test namespace"],"tags":["cli","parameter-validation","persistence","bookkeeper"],"backgroundTag":"invalid-numeric-argument","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"}