{"record":{"id":"d33bb67e65127017","repo":"apache/cassandra","slug":"0x0000","errorCode":"0x0000","errorMessage":"Cannot rebuild index %s as another index build for the same index is currently in progress.","messagePattern":"Cannot rebuild index (.+?) as another index build for the same index is currently in progress\\.","errorType":"exception","errorClass":"java.lang.IllegalStateException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/index/SecondaryIndexManager.java","lineNumber":816,"sourceCode":"     * @param isFullRebuild {@code true} if this method is invoked as a full index rebuild, {@code false} otherwise\n     * @param isNewCF {@code true} if this method is invoked when initializing a new table/columnfamily (i.e. loading a CF at startup),\n     * {@code false} for all other cases (i.e. newly added index)\n     */\n    @VisibleForTesting\n    public synchronized void markIndexesBuilding(Set<Index> indexes, boolean isFullRebuild, boolean isNewCF)\n    {\n        String keyspaceName = baseCfs.getKeyspaceName();\n\n        // First step is to validate against concurrent rebuilds; it would be more optimized to do everything on a single\n        // step, but we're not really expecting a very high number of indexes, and this isn't on any hot path, so\n        // we're favouring readability over performance\n        indexes.forEach(index ->\n                        {\n                            String indexName = index.getIndexMetadata().name;\n                            AtomicInteger counter = inProgressBuilds.computeIfAbsent(indexName, ignored -> new AtomicInteger(0));\n\n                            if (counter.get() > 0 && isFullRebuild)\n                                throw new IllegalStateException(String.format(\"Cannot rebuild index %s as another index build for the same index is currently in progress.\", indexName));\n                        });\n\n        // Second step is the actual marking:\n        indexes.forEach(index ->\n                        {\n                            String indexName = index.getIndexMetadata().name;\n                            AtomicInteger counter = inProgressBuilds.computeIfAbsent(indexName, ignored -> new AtomicInteger(0));\n\n                            if (isFullRebuild)\n                            {\n                                needsFullRebuild.remove(indexName);\n                                makeIndexNonQueryable(index, Index.Status.FULL_REBUILD_STARTED);\n                            }\n\n                            if (counter.getAndIncrement() == 0 && DatabaseDescriptor.isDaemonInitialized() && !isNewCF)\n                                SystemKeyspace.setIndexRemoved(keyspaceName, indexName);\n                        });\n    }","sourceCodeStart":798,"sourceCodeEnd":834,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/index/SecondaryIndexManager.java#L798-L834","documentation":"IllegalStateException thrown by SecondaryIndexManager.markIndexesBuilding when a full rebuild is requested for an index that already has an in-progress build (inProgressBuilds counter > 0). Prevents two concurrent builds of the same index.","triggerScenarios":"Calling rebuild of an index (REBUILD INDEXES / buildIndexesBlocking / createIndex path) while the same index is still building — e.g. issuing `nodetool rebuild_index` twice, or creating an index while its initial build is running.","commonSituations":"Ops re-running a stuck-seeming REBUILD INDEXES without waiting; schema-change and manual rebuild racing after node restart; scripted retries firing while the first build is still active.","solutions":["Wait for the current build to finish (check system.built / in-progress tasks, `nodetool compactionstats`) before rebuilding","If the first build is genuinely stuck, restart the node to clear in-progress state, then rebuild","Serialize rebuild operations in automation; do not retry in a tight loop","Use `nodetool indexbuilds`/logs to confirm the prior build completed"],"exampleFix":"// before\ncfim.rebuildIndexesBlocking(Set.of(\"idx\")); // while already building\n// after\nif (!isIndexBuilding(\"idx\")) {\n    cfim.rebuildIndexesBlocking(Set.of(\"idx\"));\n} else {\n    logger.info(\"Index idx still building; skipping rebuild\");\n}","handlingStrategy":"validation","validationCode":"// check for an in-progress build before requesting a rebuild\nif (!indexBuildsComplete(keyspace, table, indexName)) {\n    logger.info(\"Index {} still building; rebuild skipped\", indexName);\n    return;\n}","typeGuard":null,"tryCatchPattern":"try {\n    indexManager.rebuildIndexesBlocking(indexes);\n} catch (IllegalStateException e) {\n    if (e.getMessage().contains(\"currently in progress\"))\n        logger.info(\"Rebuild skipped: build already running\");\n    else throw e;\n}","preventionTips":["Wait for build completion before reissuing rebuilds (check indexbuilds/logs)","Serialize index operations in automation scripts","Avoid aggressive retries around REBUILD INDEXES","Restart node only if a build is provably hung"],"tags":["index","concurrency","rebuild","state"],"backgroundTag":"conflicting-operation-in-progress","analyzedSha":"88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1","analyzedAt":"2026-09-10T07:29:22.284Z","contentChangedAt":"2026-09-10T07:29:22.284Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}