{"record":{"id":"2d1da3f5081c33b1","repo":"provectus/kafka-ui","slug":"topic-is-already-analyzing","errorCode":null,"errorMessage":"Topic is already analyzing","messagePattern":"Topic is already analyzing","errorType":"exception","errorClass":"TopicAnalysisException","httpStatus":400,"severity":"warning","filePath":"kafka-ui-api/src/main/java/com/provectus/kafka/ui/service/analyze/TopicAnalysisService.java","lineNumber":57,"sourceCode":"      10, //ttl for idle threads (in sec)\n      true //daemon\n  );\n\n  private final AnalysisTasksStore analysisTasksStore = new AnalysisTasksStore();\n\n  private final TopicsService topicsService;\n  private final ConsumerGroupService consumerGroupService;\n\n  public Mono<Void> analyze(KafkaCluster cluster, String topicName) {\n    return topicsService.getTopicDetails(cluster, topicName)\n        .doOnNext(topic -> startAnalysis(cluster, topicName))\n        .then();\n  }\n\n  private synchronized void startAnalysis(KafkaCluster cluster, String topic) {\n    var topicId = new TopicIdentity(cluster, topic);\n    if (analysisTasksStore.isAnalysisInProgress(topicId)) {\n      throw new TopicAnalysisException(\"Topic is already analyzing\");\n    }\n    var task = new AnalysisTask(cluster, topicId);\n    analysisTasksStore.registerNewTask(topicId, task);\n    SCHEDULER.schedule(task);\n  }\n\n  public void cancelAnalysis(KafkaCluster cluster, String topicName) {\n    analysisTasksStore.cancelAnalysis(new TopicIdentity(cluster, topicName));\n  }\n\n  public Optional<TopicAnalysisDTO> getTopicAnalysis(KafkaCluster cluster, String topicName) {\n    return analysisTasksStore.getTopicAnalysis(new TopicIdentity(cluster, topicName));\n  }\n\n  class AnalysisTask implements Runnable, Closeable {\n\n    private final Instant startedAt = Instant.now();\n","sourceCodeStart":39,"sourceCodeEnd":75,"githubUrl":"https://github.com/provectus/kafka-ui/blob/83b5a60cc08501b570a0c4d0b4cdfceb1b88d6b7/kafka-ui-api/src/main/java/com/provectus/kafka/ui/service/analyze/TopicAnalysisService.java#L39-L75","documentation":"TopicAnalysisService.startAnalysis is synchronized per service and refuses to start a second analysis for the same cluster/topic while one is already registered in the analysisTasksStore, throwing TopicAnalysisException('Topic is already analyzing').","triggerScenarios":"Calling the analyze endpoint (TopicAnalysisService.analyze) twice for the same topic before the first run completes, or while a previous task is still queued/running in the scheduler.","commonSituations":"Double-clicking the 'Analyze' button; parallel CI jobs analyzing the same topic; a previous analysis stuck (large topic) and user retries; multiple browser tabs.","solutions":["Wait for the current analysis to finish before starting a new one","Check analysis status via the stats/analysis endpoint instead of re-triggering","Restart the application or cancel/stop the running analysis task if it is stuck","Deduplicate requests client-side (disable button while analysis in progress)"],"exampleFix":"// before\nanalyzeTopic(cluster, topic); // may throw if running\nanalyzeTopic(cluster, topic); // second call throws\n// after\nif (!getAnalysisStatus(cluster, topic).isInProgress()) {\n  analyzeTopic(cluster, topic);\n}","handlingStrategy":"validation","validationCode":"// Java (caller)\nTopicAnalysisStatusDTO st = topicAnalysisService.analyzeStatus(cluster, topicName); // via API endpoint\nboolean inProgress = st.getStatus() == AnalysisStatusDTO.PENDING || st.getStatus() == AnalysisStatusDTO.RUNNING;\nif (!inProgress) topicAnalysisService.analyze(cluster, topicName);","typeGuard":null,"tryCatchPattern":"try {\n  topicAnalysisService.analyze(cluster, topicName);\n} catch (TopicAnalysisException e) {\n  if (\"Topic is already analyzing\".equals(e.getMessage())) {\n    log.info(\"Analysis already running for {}:{} — skipping\", cluster, topicName);\n  } else { throw e; }\n}","preventionTips":["Check analysis status before triggering","Debounce/disable the Analyze action while a run is in progress","Serialize analysis triggers in CI (single job per topic)","If a task is stuck, stop the analysis via the API before restarting"],"tags":["kafka","topic-analysis","concurrency","state"],"backgroundTag":"invalid-state-transition","analyzedSha":"83b5a60cc08501b570a0c4d0b4cdfceb1b88d6b7","analyzedAt":"2026-09-08T04:35:39.002Z","contentChangedAt":"2026-09-08T04:35:39.002Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}