{"record":{"id":"b3e7a5bca80437a9","repo":"apache/cassandra","slug":"keyspace-is-already-added-to-fetch-map","errorCode":null,"errorMessage":"Keyspace is already added to fetch map","messagePattern":"Keyspace is already added to fetch map","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/dht/RangeStreamer.java","lineNumber":409,"sourceCode":"\n        Multimap<InetAddressAndPort, FetchReplica> workMap;\n        //Only use the optimized strategy if we don't care about strict sources, have a replication factor > 1, and no\n        //transient replicas or it is intentionally skipped.\n        if (CassandraRelevantProperties.SKIP_OPTIMAL_STREAMING_CANDIDATES_CALCULATION.getBoolean() ||\n            useStrictSource ||\n            strat == null ||\n            strat.getReplicationFactor().allReplicas == 1 ||\n            strat.getReplicationFactor().hasTransientReplicas())\n        {\n            workMap = convertPreferredEndpointsToWorkMap(fetchMap);\n        }\n        else\n        {\n            workMap = getOptimizedWorkMap(fetchMap, sourceFilters, keyspaceName, metadata.locator);\n        }\n\n        if (toFetch.put(keyspaceName, workMap) != null)\n            throw new IllegalArgumentException(\"Keyspace is already added to fetch map\");\n\n        if (logger.isTraceEnabled())\n        {\n            for (Map.Entry<InetAddressAndPort, Collection<FetchReplica>> entry : workMap.asMap().entrySet())\n            {\n                for (FetchReplica r : entry.getValue())\n                    logger.trace(\"{}: range source {} local range {} for keyspace {}\", description, r.remote, r.local, keyspaceName);\n            }\n        }\n    }\n\n    /**\n     * @param strat AbstractReplicationStrategy of keyspace to check\n     * @return true when the node is bootstrapping, useStrictConsistency is true and # of nodes in the cluster is more than # of replica\n     */\n    private boolean useStrictSourcesForRanges(ReplicationParams params, AbstractReplicationStrategy strat)\n    {\n        return useStrictSourcesForRanges(params, strat, metadata, useStrictConsistency, movements, strictMovements);","sourceCodeStart":391,"sourceCodeEnd":427,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/dht/RangeStreamer.java#L391-L427","documentation":"RangeStreamer.addKeyspaceToFetch() registers the computed per-keyspace fetch work map exactly once during bootstrap/rebuild streaming. If a keyspace is already present in the toFetch map, it throws IllegalArgumentException to prevent duplicate/conflicting streaming plans for the same keyspace.","triggerScenarios":"Calling addKeyspaceToFetch twice with the same keyspaceName — e.g. bootstrap or rebuild invoked concurrently or re-entered for the same keyspace without resetting the RangeStreamer.","commonSituations":"Concurrent or double-invoked bootstrap/rebuild scripts (nodetool bootstrap/rebuild run twice); operational tooling retrying a failed call without recreating the RangeStreamer; test harnesses reusing the streamer across keyspaces with duplicate names.","solutions":["Ensure only one bootstrap/rebuild invocation runs at a time for a node (serialize operational scripts)","If retrying after a failure, recreate/restart the streaming operation rather than re-adding keyspaces to the same RangeStreamer instance","Check logs / system.batches (or the failed streaming state) to confirm whether streaming already started for that keyspace before re-running"],"exampleFix":"// before\nstreamer.addKeyspaceToFetch(ranges, keyspace, useStrict);\nstreamer.addKeyspaceToFetch(ranges, keyspace, useStrict); // throws\n// after\nif (!alreadyFetched.contains(keyspace))\n    streamer.addKeyspaceToFetch(ranges, keyspace, useStrict);","handlingStrategy":"try-catch","validationCode":"if (toFetch.containsKey(keyspaceName)) throw new IllegalStateException(keyspaceName + \" already queued for streaming\");","typeGuard":null,"tryCatchPattern":"try { streamer.addKeyspaceToFetch(ranges, keyspace, useStrict); } catch (IllegalArgumentException e) { if (e.getMessage().contains(\"already added to fetch map\")) { log.warn(\"Skipping duplicate keyspace {}\", keyspace); } else throw e; }","preventionTips":["Serialize bootstrap/rebuild invocations per node","Track fetched keyspaces in a Set before calling addKeyspaceToFetch","Recreate the RangeStreamer for retry attempts rather than reusing it"],"tags":["streaming","bootstrap","duplicate-state"],"backgroundTag":"invalid-state-transition","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"}