eclipse-vertx/vert.x · error · VertxException
Nesting more than two levels is not supported
Error message
Nesting more than two levels is not supported
What it means
FileResolverImpl.unpackFromJarURL throws this VertxException when it encounters a jar-within-jar (or deeper) URL scheme while extracting a resource from an embedded jar. Vert.x's file resolver only understands at most two levels of nesting (e.g. an entry inside a jar), and any deeper 'jar:file:...!/...!/...' URL falls into the default switch branch. It is an internal invariant check protecting the unpacking algorithm, not a user-recoverable condition.
Source
Thrown at vertx-core/src/main/java/io/vertx/core/file/impl/FileResolverImpl.java:364
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
Path relative = path.relativize(file);
cache.cacheFile(relative.toString(), file.toFile(), false);
return FileVisitResult.CONTINUE;
}
});
} else {
// jar:file:/path/to/nesting.jar!/path/to/nested.jar
try (ZipFile zip = new ZipFile(root)) {
extractFilesFromJarFile(zip, fileName);
}
}
} else {
throw new VertxException("Unexpected nested url : " + nestedURL);
}
break;
default:
throw new VertxException("Nesting more than two levels is not supported");
}
} catch (IOException e) {
throw new VertxException(FileSystemImpl.getFileAccessErrorMessage("unpack", url.toString()), e);
}
return cache.getFile(fileName);
}
/**
* Extract a subset of the entries to the cache.
*/
private void extractFilesFromJarFile(ZipFile zip, String entryFilter) throws IOException {
Enumeration<? extends ZipEntry> entries = zip.entries();
while (entries.hasMoreElements()) {
ZipEntry entry = entries.nextElement();
String name = entry.getName();
int len = name.length();
if (len == 0) {
return;View on GitHub (pinned to fb308bd8c3)
Solutions
- Run the application as a single-level fat jar (use the standard vertx-maven-plugin / gradle shadowJar packaging) so resources sit directly in the top jar.
- If using Spring Boot nested jars, launch via Spring Boot's launcher/classloader rather than Vert.x's FileResolver, or extract the jar before running (java -Dvertx.disableFileCPResolving=true after unpacking).
- Set vertx.disableFileCPResolving=true and copy the resource out yourself with java.util.zip APIs that support arbitrary nesting.
- Restructure the artifact so the resource is a direct classpath entry (move it out of the nested jar).
Example fix
// before: resources inside a Spring Boot nested jar read via vertx.fileSystem().readFile("config.json")
// after: launch with Boot loader or extract first
java -jar app.jar // Boot LaunchedURLClassLoader handles nesting
// or in Docker:
RUN java -Djarmode=tools -jar app.jar extract --destination /app
ENTRYPOINT ["java", "-jar", "/app/app.jar"] Defensive patterns
Strategy: validation
Validate before calling
URL url = cl.getResource(name);
int depth = 0;
for (int i = 0; i < url.toString().length() - 1; i++)
if (url.toString().charAt(i) == '!' && url.toString().charAt(i + 1) == '/') depth++;
if (depth > 1) throw new IllegalStateException(
"Resource nested more than two levels deep: " + url +
" — flatten the jar layout or disable FileCP resolving"); Type guard
static boolean isOverlyNestedJarUrl(URL url) {
String s = url.toString();
return s.startsWith("jar:") && s.split("!").length > 2;
} Try / catch
try {
vertx.fileSystem().readFileBlocking(resource);
} catch (VertxException e) {
if (e.getMessage().contains("Nesting more than two levels")) {
// fall back to ClassLoader stream read
} else throw e;
} Prevention
- Package a single-level fat jar with vertx-maven-plugin or Gradle shadowJar
- Do not run Spring Boot nested-jar layouts under plain Vert.x classloading
- Avoid repackaging/shading an already-assembled fat jar
- Read nested resources via ClassLoader streams instead of file-system APIs
When it happens
Trigger: Calling vertx.fileSystem().propsAsync/copy etc. (or deploying verticles) where a resource on the classpath resolves to a URL with more than two '!' nesting levels, typically 'jar:jar:file:...!/inner.jar!/resource' produced by fat jars nested inside fat jars or Spring Boot nested-jar layout used without its own classloader.
Common situations: Spring Boot executable jars (Boot's nested jar: URLs) run through plain Vert.x classloading; shading an uber-jar that itself gets repackaged; running from a jar extracted into another jar by a build plugin; container images that bundle the app jar inside a second jar.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- Failed to unpack ${url}
- Failed to copy ${from} to ${to}
- Failed to move ${from} to ${to}
- Cannot truncate file to size < 0
- Cannot truncate file ${path}. Does not exist
AI-assisted analysis of eclipse-vertx/vert.x@fb308bd8c3 (2026-09-06).
Data as JSON: /api/errors/c7fe47ea301e2fd8.
Report an issue: GitHub.