SonarSource/sonarqube · critical
Property '%s' is not valid, not a directory: %s
Error message
Property '%s' is not valid, not a directory: %s
What it means
AppFileSystem validates configured SonarQube directories (data, temp, etc.) before use. ensureIsNotAFile throws this IllegalStateException when a path given via a *path* property exists but is a regular file instead of a directory, since the server needs to create/clean directories at that location.
Source
Thrown at server/sonar-main/src/main/java/org/sonar/application/AppFileSystem.java:87
public File getTempDir() {
return settings.getProps().nonNullValueAsFile(PATH_TEMP.getKey());
}
private boolean createDirectory(String propKey) throws IOException {
File dir = settings.getProps().nonNullValueAsFile(propKey);
if (dir.exists()) {
ensureIsNotAFile(propKey, dir);
return false;
}
forceMkdir(dir);
ensureIsNotAFile(propKey, dir);
return true;
}
private static void ensureIsNotAFile(String propKey, File dir) {
if (!dir.isDirectory()) {
throw new IllegalStateException(format("Property '%s' is not valid, not a directory: %s",
propKey, dir.getAbsolutePath()));
}
}
private File createOrCleanTempDirectory(String propKey) throws IOException {
File dir = settings.getProps().nonNullValueAsFile(propKey);
LOG.info("Cleaning or creating temp directory {}", dir.getAbsolutePath());
if (!createDirectory(propKey)) {
Files.walkFileTree(dir.toPath(), FOLLOW_LINKS, CleanTempDirFileVisitor.VISIT_MAX_DEPTH, new CleanTempDirFileVisitor(dir.toPath()));
}
return dir;
}
private static class CleanTempDirFileVisitor extends SimpleFileVisitor<Path> {
private static final Path SHAREDMEMORY_FILE = Paths.get("sharedmemory");
static final int VISIT_MAX_DEPTH = 1;
private final Path path;View on GitHub (pinned to 184c821202)
Solutions
- Inspect the property named in the message and change sonar.path.* to point to a directory (or remove it to use the default).
- Move or delete the offending file so the server can create the directory there.
- Check filesystem permissions/ownership so the sonarqube user can access the intended directory.
- In containers/orchestrations, fix volume mounts so a directory is mounted, not a file.
Example fix
// before (conf/sonar.properties) sonar.path.data=/opt/sonarqube/backup.tar.gz // after sonar.path.data=/opt/sonarqube/data
Defensive patterns
Strategy: validation
Validate before calling
for (String key : List.of("sonar.path.data", "sonar.path.temp", "sonar.path.logs", "sonar.path.web")) {
String v = props.get(key);
if (v != null && new File(v).exists() && !new File(v).isDirectory()) {
throw new IllegalStateException(key + " must be a directory, got file: " + v);
}
} Try / catch
try { fileSystem.createDirectory(propKey); } catch (IllegalStateException e) { log.severe(e.getMessage()); System.exit(1); } Prevention
- Point sonar.path.* properties at directories, never at files.
- Validate sonar.properties paths after config-management changes.
- Use dedicated directories (data/, temp/, logs/) with correct ownership.
- In containers, mount volumes as directories explicitly.
When it happens
Trigger: A sonar.path.* property (e.g. sonar.path.data, sonar.path.temp, sonar.path.logs) points at an existing regular file, so dir.isDirectory() is false when createDirectory() runs during server startup.
Common situations: Config mistakes where a path property was set to a file (e.g. a tarball or log file) instead of a directory; a leftover file created accidentally at the expected directory path; bind-mounting a file where a directory is expected in containers.
Related errors
- Cannot open file
- Directory does not exist:
- Directory must contain only one JAR file:
- JVM option '%s' must be set to '%s'. Got '%s'
- Fail to create or clean-up directory %s
AI-assisted analysis of SonarSource/sonarqube@184c821202 (2026-09-09).
Data as JSON: /api/errors/894d597a4f9c0153.
Report an issue: GitHub.