SonarSource/sonarqube · error · IllegalStateException
Already started
Error message
Already started
What it means
ProcessEntryPoint.launch guards against double-startup by moving the lifecycle to STARTING atomically. If the process (or this entry point) is already started, the transition fails and IllegalStateException 'Already started' is thrown.
Source
Thrown at server/sonar-process/src/main/java/org/sonar/process/ProcessEntryPoint.java:75
this.stopWatcher = createStopWatcher(commands, this);
this.hardStopWatcher = createHardStopWatcher(commands, this);
this.runtime = runtime;
}
public ProcessCommands getCommands() {
return commands;
}
public Props getProps() {
return props;
}
/**
* Launch process and waits until it's down
*/
public void launch(Monitored mp) {
if (!lifecycle.tryToMoveTo(Lifecycle.State.STARTING)) {
throw new IllegalStateException("Already started");
}
monitored = mp;
Logger logger = LoggerFactory.getLogger(getClass());
try {
launch(logger);
} catch (Exception e) {
logger.warn("Fail to start {}", processId.getHumanReadableName(), e);
hardStop();
}
}
private void launch(Logger logger) throws InterruptedException {
logger.info("Starting {}", processId.getHumanReadableName());
runtime.addShutdownHook(new Thread(() -> {
exit.setInShutdownHook();
stop();
}));View on GitHub (pinned to 184c821202)
Solutions
- Create a new ProcessEntryPoint instance for each launch
- Ensure launch is called only once per JVM/process
- Check the lifecycle state before calling launch
- Refactor tests to instantiate a fresh entry point per test
Example fix
// before ProcessEntryPoint entry = ProcessEntryPoint.create(props); entry.launch(monitored); entry.launch(monitored); // throws // after ProcessEntryPoint entry = ProcessEntryPoint.create(props); entry.launch(monitored); // single launch per instance
Defensive patterns
Strategy: validation
Validate before calling
if (lifecycle.getState() != Lifecycle.State.INIT) {
throw new IllegalStateException("ProcessEntryPoint already launched");
} Try / catch
try {
entryPoint.launch(monitored);
} catch (IllegalStateException e) {
if ("Already started".equals(e.getMessage())) { LOGGER.warn("launch called twice; ignoring"); } else throw e;
} Prevention
- Call launch exactly once per ProcessEntryPoint instance
- Create a fresh instance for every restart
- Guard shared entry points in tests with state flags
When it happens
Trigger: Calling launch(monitor) twice on the same ProcessEntryPoint instance, or reusing a shutdown/restarted lifecycle.
Common situations: Testing code calling launch repeatedly on a shared entry point; wrapper scripts relaunching in the same JVM; accidental double invocation in main.
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
- Dump is already published
- Metadata has already been written
- Metadata is missing
- Fail to connect to database
- Failed to create table schema_migrations
AI-assisted analysis of SonarSource/sonarqube@184c821202 (2026-09-09).
Data as JSON: /api/errors/4d2159abade15e48.
Report an issue: GitHub.