SonarSource/sonarqube · error · IllegalStateException

"Cannot detect path of shutdowner jar file"

Error message

"Cannot detect path of shutdowner jar file"

What it means

Shutdowner.detectHomeDir locates the SonarQube home directory by resolving the URI of the shutdowner jar's code source and taking two parent directories. If the code source location cannot be converted to a URI (URISyntaxException), it throws IllegalStateException "Cannot detect path of shutdowner jar file". This only happens when the class was loaded from a non-file URI (unusual classloader) or a malformed location.

Source

Thrown at sonar-shutdowner/src/main/java/org/sonar/application/Shutdowner.java:61

    }
  }

  void run() throws IOException {
    File homeDir = detectHomeDir();
    Properties p = loadPropertiesFile(homeDir);
    File tmpDir = resolveTempDir(p);

    askForHardStop(tmpDir);
  }

  // assuming jar file is in directory SQ_HOME/lib/

  static File detectHomeDir() {
    try {
      File appJar = new File(Shutdowner.class.getProtectionDomain().getCodeSource().getLocation().toURI());
      return appJar.getParentFile().getParentFile();
    } catch (URISyntaxException e) {
      throw new IllegalStateException("Cannot detect path of shutdowner jar file", e);
    }
  }

  /**
   * Loads the configuration file ${homeDir}/conf/sonar.properties.
   * An empty {@link Properties} is returned if the file does not exist.
   */
  static Properties loadPropertiesFile(File homeDir) {
    Properties p = new Properties();
    File propsFile = new File(new File(homeDir, "conf"), "sonar.properties");
    if (propsFile.exists()) {
      try (Reader reader = new InputStreamReader(new FileInputStream(propsFile), UTF_8)) {
        p.load(reader);
        return p;
      } catch (IOException e) {
        throw new IllegalStateException("Cannot open file " + propsFile, e);
      }
    } else {

View on GitHub (pinned to 184c821202)

Solutions

  1. Run the shutdowner from the standard SonarQube distribution layout (lib/sonar-shutdowner-*.jar under home dir).
  2. Set SONARQUBE_HOME / launch via the official bin scripts so the jar path is a plain file URI.
  3. Check the URISyntaxException cause for the malformed URI and fix the classpath entry.
  4. Upgrade the JVM if an old version mis-encodes paths with spaces.

Example fix

// before: launching via custom classloader where code source is not a file
java -cp exotic-loader.jar org.sonar.application.Shutdowner

// after: use the distribution launcher so the jar location is a file URI
$SONARQUBE_HOME/bin/<os>/sonar.sh stop
Defensive patterns

Strategy: fallback

Validate before calling

// Java
URI uri = Shutdowner.class.getProtectionDomain().getCodeSource().getLocation().toURI();
boolean isFile = "file".equals(uri.getScheme());

Try / catch

// Java
try {
  File home = Shutdowner.detectHomeDir();
} catch (IllegalStateException e) {
  // fall back to SONARQUBE_HOME env var or explicit -Dsonar.home
}

Prevention

When it happens

Trigger: Starting Shutdowner via homeDir()/detectHomeDir() when Shutdowner.class.getProtectionDomain().getCodeSource().getLocation().toURI() throws URISyntaxException, e.g. class loaded from a URL/network path or an exotic custom classloader.

Common situations: Running the shutdowner class outside the standard SONARQUBE_HOME layout (extracted/repackaged jar, running from an IDE or fat jar with a non-file code source); corrupted Java installation producing malformed URIs (e.g. spaces mishandled by old JVMs).

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


AI-assisted analysis of SonarSource/sonarqube@184c821202 (2026-09-09). Data as JSON: /api/errors/ce834bee8b8c1301. Report an issue: GitHub.