{"record":{"id":"39129c8028d7029d","repo":"apache/cassandra","slug":"training-already-in-progress-for-table-keyspacena","errorCode":null,"errorMessage":"Training already in progress for table <keyspaceName>.<tableName>","messagePattern":"Training already in progress for table <keyspaceName>\\.<tableName>","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"warning","filePath":"src/java/org/apache/cassandra/db/compression/CompressionDictionaryScheduler.java","lineNumber":100,"sourceCode":"        this.scheduledRefreshTask = ScheduledExecutors.scheduledTasks.scheduleWithFixedDelay(\n        this::refreshDictionaryFromSystemTable,\n        DatabaseDescriptor.getCompressionDictionaryRefreshInitialDelaySeconds(),\n        DatabaseDescriptor.getCompressionDictionaryRefreshIntervalSeconds(),\n        TimeUnit.SECONDS\n        );\n    }\n\n    @Override\n    public void scheduleSSTableBasedTraining(ColumnFamilyStore.RefViewFragment refViewFragment,\n                                             CompressionParams compressionParams,\n                                             CompressionDictionaryTrainingConfig config,\n                                             Consumer<CompressionDictionary> listener,\n                                             boolean force)\n    {\n        if (!trainingInProgress.compareAndSet(false, true))\n        {\n            refViewFragment.close();\n            throw new IllegalStateException(\"Training already in progress for table \" + keyspaceName + '.' + tableName);\n        }\n\n        ICompressionDictionaryTrainer trainer;\n\n        try\n        {\n            trainer = ICompressionDictionaryTrainer.create(keyspaceName, tableName, compressionParams);\n            trainer.setDictionaryTrainedListener(listener);\n        }\n        catch (Throwable t)\n        {\n            trainingInProgress.set(false);\n            refViewFragment.close();\n            throw t;\n        }\n\n        if (trainer.start(config))\n        {","sourceCodeStart":82,"sourceCodeEnd":118,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/db/compression/CompressionDictionaryScheduler.java#L82-L118","documentation":"CompressionDictionaryScheduler serializes SSTable-based training per table using an atomic trainingInProgress flag. If scheduleSSTableBasedTraining() is invoked while a training run is already in flight for the same table, the CAS fails, the referenced SSTable view is released, and IllegalStateException is thrown. Only one training at a time per table is permitted.","triggerScenarios":"Calling scheduleSSTableBasedTraining() (via train() or scheduled compaction-triggered training) while another training session for the same keyspace.table has not yet completed.","commonSituations":"Two operators or scripts triggering training concurrently; a scheduled periodic trainer overlapping a manual training; a slow/stuck previous training run still holding the flag when a new request arrives.","solutions":["Wait for the in-progress training to complete before requesting another; check the training status via JMX first.","Catch IllegalStateException and treat it as 'training already running' rather than an error in automation.","Serialize training requests through a single job/queue per table.","If a previous training appears stuck, investigate/restart the node to clear the flag rather than forcing concurrent runs."],"exampleFix":"// before\ntry { manager.train(true, params); }\ncatch (Exception e) { throw e; }\n// after\ntry { manager.train(true, params); }\ncatch (IllegalStateException e) {\n    if (e.getMessage().contains(\"Training already in progress\")) return; // already running\n    throw e;\n}","handlingStrategy":"try-catch","validationCode":"if (!manager.isTrainingInProgress()) manager.train(force, params);","typeGuard":null,"tryCatchPattern":"try { manager.train(force, params); } catch (IllegalStateException e) { if (e.getMessage().contains(\"already in progress\")) { /* skip or retry later */ } else throw e; }","preventionTips":["Serialize training triggers through one scheduler per table","Check training status via JMX before manual triggers","Alert on unusually long in-progress training runs"],"tags":["compression","training","concurrency"],"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"}