{"record":{"id":"368fcfa3840ec06c","repo":"apache/cassandra","slug":"amount-of-transient-nodes-should-be-strictly-posit","errorCode":null,"errorMessage":"Amount of transient nodes should be strictly positive, but was: '%d'","messagePattern":"Amount of transient nodes should be strictly positive, but was: '(.+?)'","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/locator/ReplicationFactor.java","lineNumber":83,"sourceCode":"                                    \"Transient replication is not enabled on this node\");\n        Preconditions.checkArgument(totalRF >= 0,\n                                    \"Replication factor must be non-negative, found %s\", totalRF);\n        Preconditions.checkArgument(transientRF == 0 || transientRF < totalRF,\n                                    \"Transient replicas must be zero, or less than total replication factor. For %s/%s\", totalRF, transientRF);\n        if (transientRF > 0)\n        {\n            Preconditions.checkArgument(DatabaseDescriptor.getNumTokens() == 1,\n                                        \"Transient nodes are not allowed with multiple tokens\");\n            Stream<InetAddressAndPort> endpoints = Stream.concat(Gossiper.instance.getLiveMembers().stream(), Gossiper.instance.getUnreachableMembers().stream());\n            List<InetAddressAndPort> badVersionEndpoints = endpoints.filter(Predicates.not(FBUtilities.getBroadcastAddressAndPort()::equals))\n                                                                    .filter(endpoint -> Gossiper.instance.getReleaseVersion(endpoint) != null && Gossiper.instance.getReleaseVersion(endpoint).major < 4)\n                                                                    .collect(Collectors.toList());\n            if (!badVersionEndpoints.isEmpty())\n                throw new IllegalArgumentException(\"Transient replication is not supported in mixed version clusters with nodes < 4.0. Bad nodes: \" + badVersionEndpoints);\n        }\n        else if (transientRF < 0)\n        {\n            throw new IllegalArgumentException(String.format(\"Amount of transient nodes should be strictly positive, but was: '%d'\", transientRF));\n        }\n    }\n\n    public boolean equals(Object o)\n    {\n        if (this == o) return true;\n        if (o == null || getClass() != o.getClass()) return false;\n        ReplicationFactor that = (ReplicationFactor) o;\n        return allReplicas == that.allReplicas && fullReplicas == that.fullReplicas;\n    }\n\n    public int hashCode()\n    {\n        return Objects.hash(allReplicas, fullReplicas);\n    }\n\n    public static ReplicationFactor fullOnly(int totalReplicas)\n    {","sourceCodeStart":65,"sourceCodeEnd":101,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/locator/ReplicationFactor.java#L65-L101","documentation":"When parsing a replication factor string with a transient component, the transient RF count must be strictly positive (the '/0' case is rejected) and never negative. ReplicationFactor.validate throws this IllegalArgumentException if the transient portion is negative, indicating malformed replication syntax.","triggerScenarios":"Defining replication with a negative transient count, e.g. 'dc1':'3/-1', or programmatic construction of a ReplicationFactor with transientRF < 0 (note: transientRF == 0 is also rejected when a '/' separator was present).","commonSituations":"Typo in the RF string in CREATE KEYSPACE; scripted generation of replication options with unvalidated/interpolated numbers; misconfigured tooling emitting 'n/-m'.","solutions":["Fix the replication string so the transient count is a positive integer, e.g. 'dc1':'5/1'","Validate that transient replicas < full replicas before submitting the schema change","Re-run the CREATE/ALTER KEYSPACE with the corrected value"],"exampleFix":"// before\nCREATE KEYSPACE ks WITH replication = {'class':'NetworkTopologyStrategy','dc1':'5/-1'};\n// after\nCREATE KEYSPACE ks WITH replication = {'class':'NetworkTopologyStrategy','dc1':'5/1'};","handlingStrategy":"validation","validationCode":"static ReplicationFactor parseRf(String s) {\n    String[] parts = s.split(\"/\");\n    int full = Integer.parseInt(parts[0]);\n    int transientRf = parts.length > 1 ? Integer.parseInt(parts[1]) : 0;\n    if (transientRf < 0) throw new IllegalArgumentException(\"transient RF must be > 0: \" + s);\n    if (transientRf >= full) throw new IllegalArgumentException(\"transient RF must be < full RF: \" + s);\n    return ReplicationFactor.fromString(s);\n}","typeGuard":null,"tryCatchPattern":"try { session.execute(createKeyspaceCql); }\ncatch (InvalidQueryException e) { if (e.getMessage().contains(\"transient\")) { /* correct the RF string and retry */ } }","preventionTips":["Validate RF strings ('n/m' with 0 < m < n) in schema tooling before applying","Use constants/templates instead of interpolating raw numbers into replication maps","Add schema linting in CI for keyspace definitions"],"tags":["transient-replication","invalid-value","configuration"],"backgroundTag":"invalid-argument-value","analyzedSha":"88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1","analyzedAt":"2026-09-10T07:29:22.284Z","contentChangedAt":"2026-09-10T07:29:22.284Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}