{"record":{"id":"ce834bee8b8c1301","repo":"SonarSource/sonarqube","slug":"cannot-detect-path-of-shutdowner-jar-file","errorCode":null,"errorMessage":"\"Cannot detect path of shutdowner jar file\"","messagePattern":"\"Cannot detect path of shutdowner jar file\"","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"sonar-shutdowner/src/main/java/org/sonar/application/Shutdowner.java","lineNumber":61,"sourceCode":"    }\n  }\n\n  void run() throws IOException {\n    File homeDir = detectHomeDir();\n    Properties p = loadPropertiesFile(homeDir);\n    File tmpDir = resolveTempDir(p);\n\n    askForHardStop(tmpDir);\n  }\n\n  // assuming jar file is in directory SQ_HOME/lib/\n\n  static File detectHomeDir() {\n    try {\n      File appJar = new File(Shutdowner.class.getProtectionDomain().getCodeSource().getLocation().toURI());\n      return appJar.getParentFile().getParentFile();\n    } catch (URISyntaxException e) {\n      throw new IllegalStateException(\"Cannot detect path of shutdowner jar file\", e);\n    }\n  }\n\n  /**\n   * Loads the configuration file ${homeDir}/conf/sonar.properties.\n   * An empty {@link Properties} is returned if the file does not exist.\n   */\n  static Properties loadPropertiesFile(File homeDir) {\n    Properties p = new Properties();\n    File propsFile = new File(new File(homeDir, \"conf\"), \"sonar.properties\");\n    if (propsFile.exists()) {\n      try (Reader reader = new InputStreamReader(new FileInputStream(propsFile), UTF_8)) {\n        p.load(reader);\n        return p;\n      } catch (IOException e) {\n        throw new IllegalStateException(\"Cannot open file \" + propsFile, e);\n      }\n    } else {","sourceCodeStart":43,"sourceCodeEnd":79,"githubUrl":"https://github.com/SonarSource/sonarqube/blob/184c821202192afc1c599fc912d0889b69fffa53/sonar-shutdowner/src/main/java/org/sonar/application/Shutdowner.java#L43-L79","documentation":"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.","triggerScenarios":"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.","commonSituations":"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).","solutions":["Run the shutdowner from the standard SonarQube distribution layout (lib/sonar-shutdowner-*.jar under home dir).","Set SONARQUBE_HOME / launch via the official bin scripts so the jar path is a plain file URI.","Check the URISyntaxException cause for the malformed URI and fix the classpath entry.","Upgrade the JVM if an old version mis-encodes paths with spaces."],"exampleFix":"// before: launching via custom classloader where code source is not a file\njava -cp exotic-loader.jar org.sonar.application.Shutdowner\n\n// after: use the distribution launcher so the jar location is a file URI\n$SONARQUBE_HOME/bin/<os>/sonar.sh stop","handlingStrategy":"fallback","validationCode":"// Java\nURI uri = Shutdowner.class.getProtectionDomain().getCodeSource().getLocation().toURI();\nboolean isFile = \"file\".equals(uri.getScheme());","typeGuard":null,"tryCatchPattern":"// Java\ntry {\n  File home = Shutdowner.detectHomeDir();\n} catch (IllegalStateException e) {\n  // fall back to SONARQUBE_HOME env var or explicit -Dsonar.home\n}","preventionTips":["Launch via the official SonarQube bin scripts so the jar path is a plain file URI.","Do not load the shutdowner class from custom classloaders or remote code sources.","Set SONARQUBE_HOME explicitly in service configurations.","Upgrade old JVMs that mishandle paths with special characters."],"tags":["shutdowner","classpath","sonarqube","home-directory"],"backgroundTag":"internal-invariant-violation","analyzedSha":"184c821202192afc1c599fc912d0889b69fffa53","analyzedAt":"2026-09-09T12:23:51.573Z","contentChangedAt":"2026-09-09T12:23:51.573Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}