SonarSource/sonarqube · error · IllegalStateException
Can get file ${filename}
Error message
Can get file ${filename} What it means
BatchIndex.getFile resolves a scanner-provided filename inside the batch working directory and returns it as a File. If the resolved path escapes batchDir (path traversal check via FilenameUtils.directoryContains) or does not exist, a NotFoundException is thrown; if resolving canonical paths or checking existence throws an IOException, it is wrapped in this IllegalStateException. It guards the batch download endpoint against bad or malicious filenames.
Source
Thrown at server/sonar-webserver-webapi/src/main/java/org/sonar/server/batch/BatchIndex.java:94
@Override
public void stop() {
// Nothing to do
}
String getIndex() {
return index;
}
File getFile(String filename) {
try {
File input = new File(batchDir, filename);
if (!FilenameUtils.directoryContains(batchDir.getCanonicalPath(), input.getCanonicalPath()) || !input.exists()) {
throw new NotFoundException("Bad filename: " + filename);
}
return input;
} catch (IOException e) {
throw new IllegalStateException("Can get file " + filename, e);
}
}
}
View on GitHub (pinned to 184c821202)
Solutions
- Re-run the scanner so it re-requests a freshly generated batch manifest
- Check the file still exists in the batch directory and that batchDir/files were not pruned
- Verify the filename in the request has no path separators or '..' segments
- Ensure the batch directory is not a symlink and no canonicalization mismatch (different mounts, case-insensitive FS)
Example fix
// before File input = new File(batchDir, filename); // after File input = new File(batchDir, new File(filename).getName()); // strip path components before resolution
Defensive patterns
Strategy: validation
Validate before calling
if (filename.contains("/") || filename.contains("..")) throw new IllegalArgumentException("bad filename");
// also ensure the file was listed in the current batch manifest before requesting it Try / catch
try { File f = batchIndex.getFile(filename); } catch (NotFoundException e) { reRequestBatch(); } Prevention
- Never persist batch file URLs across server restarts or long waits
- Sanitize filename inputs to a bare name
- Keep batch directories alive for the duration of the scan
When it happens
Trigger: GET of a batch/file resource where the filename contains path separators or '..' so canonicalization fails mid-check, or the underlying file is deleted/renamed between the exists() check and canonical path computation causing an IOException.
Common situations: Scanner caching a file URL and the server's batch directory being cleaned up (temp cleanup, restart) before download; corrupted or hand-crafted scanner requests with traversal-style filenames; symlinked batch directories breaking canonical-path containment.
Understand the failure class
Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.
Related errors
- Plugin [%s] does not exist
- Unknown severity: %s
- Identity provider %s does not exist or is not enabled
- Authentication is required
- Insufficient privileges
AI-assisted analysis of SonarSource/sonarqube@184c821202 (2026-09-09).
Data as JSON: /api/errors/d36ac640a7a6082d.
Report an issue: GitHub.