provectus/kafka-ui · warning · TopicAnalysisException
Topic is already analyzing
Error message
Topic is already analyzing
What it means
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').
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)
Example fix
// before
analyzeTopic(cluster, topic); // may throw if running
analyzeTopic(cluster, topic); // second call throws
// after
if (!getAnalysisStatus(cluster, topic).isInProgress()) {
analyzeTopic(cluster, topic);
} Defensive patterns
Strategy: validation
Validate before calling
// Java (caller) TopicAnalysisStatusDTO st = topicAnalysisService.analyzeStatus(cluster, topicName); // via API endpoint boolean inProgress = st.getStatus() == AnalysisStatusDTO.PENDING || st.getStatus() == AnalysisStatusDTO.RUNNING; if (!inProgress) topicAnalysisService.analyze(cluster, topicName);
Try / catch
try {
topicAnalysisService.analyze(cluster, topicName);
} catch (TopicAnalysisException e) {
if ("Topic is already analyzing".equals(e.getMessage())) {
log.info("Analysis already running for {}:{} — skipping", cluster, topicName);
} else { throw e; }
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: Double-clicking the 'Analyze' button; parallel CI jobs analyzing the same topic; a previous analysis stuck (large topic) and user retries; multiple browser tabs.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- Application config isn't valid. Cluster names should be…
- Application config isn't valid. Two clusters can't have the…
- seekTo should be set if seekType is
- Schema Registry is not set for cluster
- ANY operation can be only part of filter
AI-assisted analysis of provectus/kafka-ui@83b5a60cc0 (2026-09-08).
Data as JSON: /api/errors/2d1da3f5081c33b1.
Report an issue: GitHub.
Appendix: source
Thrown at kafka-ui-api/src/main/java/com/provectus/kafka/ui/service/analyze/TopicAnalysisService.java:57
10, //ttl for idle threads (in sec)
true //daemon
);
private final AnalysisTasksStore analysisTasksStore = new AnalysisTasksStore();
private final TopicsService topicsService;
private final ConsumerGroupService consumerGroupService;
public Mono<Void> analyze(KafkaCluster cluster, String topicName) {
return topicsService.getTopicDetails(cluster, topicName)
.doOnNext(topic -> startAnalysis(cluster, topicName))
.then();
}
private synchronized void startAnalysis(KafkaCluster cluster, String topic) {
var topicId = new TopicIdentity(cluster, topic);
if (analysisTasksStore.isAnalysisInProgress(topicId)) {
throw new TopicAnalysisException("Topic is already analyzing");
}
var task = new AnalysisTask(cluster, topicId);
analysisTasksStore.registerNewTask(topicId, task);
SCHEDULER.schedule(task);
}
public void cancelAnalysis(KafkaCluster cluster, String topicName) {
analysisTasksStore.cancelAnalysis(new TopicIdentity(cluster, topicName));
}
public Optional<TopicAnalysisDTO> getTopicAnalysis(KafkaCluster cluster, String topicName) {
return analysisTasksStore.getTopicAnalysis(new TopicIdentity(cluster, topicName));
}
class AnalysisTask implements Runnable, Closeable {
private final Instant startedAt = Instant.now();
View on GitHub (pinned to 83b5a60cc0)